diff --git a/.eslintrc.js b/.eslintrc.js index 991aab5..2be3590 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,80 +1,82 @@ module.exports = { - 'env': { - 'browser': true, - 'es2020': true, - 'node': true - }, - 'extends': [ - 'eslint:recommended', - 'plugin:@typescript-eslint/recommended' - ], - 'parser': '@typescript-eslint/parser', - 'parserOptions': { - 'ecmaVersion': 6, - 'sourceType': 'module' - // 'project': './tsconfig.json', - }, - 'plugins': [ - '@typescript-eslint' - ], + env: { + browser: true, + es2020: true, + node: true, + }, + extends: ["eslint:recommended", "plugin:@typescript-eslint/recommended"], + parser: "@typescript-eslint/parser", + parserOptions: { + ecmaVersion: 6, + sourceType: "module", + // 'project': './tsconfig.json', + }, + plugins: ["@typescript-eslint"], + /** + * 规则写法 + * 1、'quotes': 0; -- 0关闭,1警告,2错误 + * 2、'quotes': 'off'; -- off关闭,warn警告,error错误 + * 3、'quotes': ['error', 'single']; 'error'是提示类型,'single'是参数。参数不止一个的时候写成{} + */ + rules: { + // 是否检查变量已申明但未使用:警告。 + "@typescript-eslint/no-unused-vars": ["warn"], + // 强制单引号:开启,自动修正 + quotes: 0, + // 强制分号:js 关闭,ts 强制分号。 + semi: ["off"], + // 'semi': ['off'], + // 定义变量时自动类型推断:关闭 + "@typescript-eslint/no-inferrable-types": ["off"], + // 强制const:关闭 + "prefer-const": ["off"], + // 不允许空函数:关闭 + "@typescript-eslint/no-empty-function": ["off"], + // 禁止特定类型:关闭。 PS:如果打开 Function 类型会报错 + "@typescript-eslint/ban-types": ["off"], + // 禁止多余的分号:关闭。 PS:打开后,某些大括号结束加分号会报错 + "@typescript-eslint/no-extra-semi": ["off"], + // 检查函数是否有返回值:警告。 PS:有些老代码没有返回值,历史包袱重,暂时不强制报错 + "@typescript-eslint/explicit-module-boundary-types": ["warn"], + // 禁止给变量赋值为 this:关闭。 + "@typescript-eslint/no-this-alias": ["off"], + // 禁止使用 requires:关闭。 + "@typescript-eslint/no-var-requires": ["off"], + // 检测无法访问的代码:关闭。 PS:有时候需要用 return 注释掉后面的代码 + "no-unreachable": ["off"], /** - * 规则写法 - * 1、'quotes': 0; -- 0关闭,1警告,2错误 - * 2、'quotes': 'off'; -- off关闭,warn警告,error错误 - * 3、'quotes': ['error', 'single']; 'error'是提示类型,'single'是参数。参数不止一个的时候写成{} + * 是否可以直接调用对象方法:关闭。 + * PS:暂时关闭。目前写法:myObject.hasOwnProperty('name') ,推荐写法:Object.prototype.hasOwnProperty.call(foo, "bar") */ - 'rules': { - // 是否检查变量已申明但未使用:警告。 - '@typescript-eslint/no-unused-vars': ['warn'], - // 强制单引号:开启,自动修正 - 'quotes': 0, - // 强制分号:js 关闭,ts 强制分号。 - 'semi': ['off'], - // 'semi': ['off'], - // 定义变量时自动类型推断:关闭 - '@typescript-eslint/no-inferrable-types': ['off'], - // 强制const:关闭 - 'prefer-const': ['off'], - // 不允许空函数:关闭 - '@typescript-eslint/no-empty-function': ['off'], - // 禁止特定类型:关闭。 PS:如果打开 Function 类型会报错 - '@typescript-eslint/ban-types': ['off'], - // 禁止多余的分号:关闭。 PS:打开后,某些大括号结束加分号会报错 - '@typescript-eslint/no-extra-semi': ['off'], - // 检查函数是否有返回值:警告。 PS:有些老代码没有返回值,历史包袱重,暂时不强制报错 - '@typescript-eslint/explicit-module-boundary-types': ['warn'], - // 禁止给变量赋值为 this:关闭。 - '@typescript-eslint/no-this-alias': ['off'], - // 禁止使用 requires:关闭。 - '@typescript-eslint/no-var-requires': ['off'], - // 检测无法访问的代码:关闭。 PS:有时候需要用 return 注释掉后面的代码 - 'no-unreachable': ['off'], - /** - * 是否可以直接调用对象方法:关闭。 - * PS:暂时关闭。目前写法:myObject.hasOwnProperty('name') ,推荐写法:Object.prototype.hasOwnProperty.call(foo, "bar") - */ - 'no-prototype-builtins': ['off'], - // 是否允许函数内定义函数:关闭。 - 'no-inner-declarations': ['off'], - // 不允许判断条件写死:关闭。 PS:打开后,if(false){} 这种判断语句会报错 - 'no-constant-condition': ['off'], - // get 和 set 是否必须放在一起:关闭。 - '@typescript-eslint/adjacent-overload-signatures': ['off'], - "no-async-promise-executor": ['off'] + "no-prototype-builtins": ["off"], + // 是否允许函数内定义函数:关闭。 + "no-inner-declarations": ["off"], + // 不允许判断条件写死:关闭。 PS:打开后,if(false){} 这种判断语句会报错 + "no-constant-condition": ["off"], + // get 和 set 是否必须放在一起:关闭。 + "@typescript-eslint/adjacent-overload-signatures": ["off"], + "no-async-promise-executor": ["off"], + "prefer-spread": ["off"], + "prefer-rest-params": ["off"], + "@typescript-eslint/no-explicit-any": ["off"], + // "function-paren-newline": ["off", { minItems: 5 }], + "max-len": ["warn", { code: 120 }], + }, + // 如果有 js 和 ts 需要分开指定的规则,就 js 写 rules 里,ts 写 overrides 里 + overrides: [ + { + // enable the rule specifically for TypeScript files + files: ["*.ts", "*.tsx"], + rules: { + // 强制分号:开启,自动修正 + semi: ["error", "always"], + // '@typescript-eslint/explicit-module-boundary-types': ['error'] + }, }, - // 如果有 js 和 ts 需要分开指定的规则,就 js 写 rules 里,ts 写 overrides 里 - 'overrides': [{ - // enable the rule specifically for TypeScript files - 'files': ['*.ts', '*.tsx'], - 'rules': { - // 强制分号:开启,自动修正 - 'semi': ['error', 'always'], - // '@typescript-eslint/explicit-module-boundary-types': ['error'] - } - }], - // 定义全局变量 - 'globals': { - 'Global': true - } + ], + // 定义全局变量 + globals: { + Global: true, + }, }; diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 823729f..9dba4aa 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -13,9 +13,7 @@ name: "CodeQL" on: push: - branches: [ "main" ] - schedule: - - cron: '45 21 * * 2' + branches: ["release"] jobs: analyze: @@ -29,43 +27,42 @@ jobs: strategy: fail-fast: false matrix: - language: [ 'javascript' ] + language: ["javascript"] # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support steps: - - name: Checkout repository - uses: actions/checkout@v3 + - name: Checkout repository + uses: actions/checkout@v3 - # Initializes the CodeQL tools for scanning. - - name: Initialize CodeQL - uses: github/codeql-action/init@v2 - with: - languages: ${{ matrix.language }} - # If you wish to specify custom queries, you can do so here or in a config file. - # By default, queries listed here will override any specified in a config file. - # Prefix the list here with "+" to use these queries and those in the config file. - - # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs - # queries: security-extended,security-and-quality + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v2 + with: + languages: ${{ matrix.language }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. - - # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). - # If this step fails, then you should remove it and run the build manually (see below) - - name: Autobuild - uses: github/codeql-action/autobuild@v2 + # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs + # queries: security-extended,security-and-quality - # ℹ️ Command-line programs to run using the OS shell. - # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun + # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). + # If this step fails, then you should remove it and run the build manually (see below) + - name: Autobuild + uses: github/codeql-action/autobuild@v2 - # If the Autobuild fails above, remove it and uncomment the following three lines. - # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. + # ℹ️ Command-line programs to run using the OS shell. + # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun - # - run: | - # echo "Run, Build Application using script" - # ./location_of_script_within_repo/buildscript.sh + # If the Autobuild fails above, remove it and uncomment the following three lines. + # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 - with: - category: "/language:${{matrix.language}}" + # - run: | + # echo "Run, Build Application using script" + # ./location_of_script_within_repo/buildscript.sh + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v2 + with: + category: "/language:${{matrix.language}}" diff --git a/CHANGELOG.md b/CHANGELOG.md index 51cfd50..0751c9e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,113 +1,159 @@ +## version 2.1.0 + +- 重构工厂模式、责任链模式 +- 去除多余模块 +- 增加所有测试用例单个提交的按钮,可以自己填写测试用例 +- 修改部分题目一键用例问题 + ## version 2.0.0 + - 重构 - 现在会从[zerotrac.github.io](https://zerotrac.github.io/leetcode_problem_rating/data.json)获取数据进行缓存 - 登录选择优化 + ## version 1.1.10 + - 更新数据 ## version 1.1.9 + - BWC90 & WC317 数据 ## version 1.1.8 + - WC316 数据 ## version 1.1.7 -- Windows环境使用VsCode自带node环境,测试用例解析问题 + +- Windows 环境使用 VsCode 自带 node 环境,测试用例解析问题 ## version 1.1.6 -- 尝试不需要安装node环境 + +- 尝试不需要安装 node 环境 ## version 1.1.5 -- 修复PreView Problem 题目元数据显示出错 + +- 修复 PreView Problem 题目元数据显示出错 ## version 1.1.4 + - BWC89 & WC315 数据 ## version 1.1.3 + - 修复每日一题隔天刷新问题 ## version 1.1.2 + - 去除多余客户端代码 ## version 1.1.1 + - 重新写原本的客户端 - 减少许多多余的包引用 ## version 1.0.24 -- 增加314期数据 + +- 增加 314 期数据 ## version 1.0.23 -- 修复README.md中GIF无法显示 + +- 修复 README.md 中 GIF 无法显示 ## version 1.0.22 + - 修复排序错误 -- 增加README.md说明 +- 增加 README.md 说明 + ## version 1.0.21 + - 修复提交全部用例问题 + ## version 1.0.20 + - 增加单次用例提交,全部用例提交的功能 ## version 1.0.19 + - 修复获取题解报错 + ## version 1.0.18 + - 增加更新状态栏的周赛数据显示 ## version 1.0.17 -- 更新312、313、双周88期 + +- 更新 312、313、双周 88 期 ## version 1.0.16 + - 修复测试用例字符串问题 - 每日一题提交后更新状态 ## version 1.0.15 -- 更换icon使得看起来不起眼 + +- 更换 icon 使得看起来不起眼 ## version 1.0.14 + - 安装插件检测 -- github问题报告模板 +- github 问题报告模板 ## version 1.0.13 + - 修复测试提交功能 ## version 1.0.12 + - 修复检出题目与标题对不上问题 ## version 1.0.11 + - 可以根据分数隐藏题目的设置 - 清除所有缓存功能 - 默认登录中国站 ## version 1.0.10 -- tag数据修复 -- 去除company分类 + +- tag 数据修复 +- 去除 company 分类 ## version 1.0.9 -- github提醒依赖安全更新 + +- github 提醒依赖安全更新 ## version 1.0.8 + - 增加精选合集分类 - 增加剑指、杯赛题目 - 每日一题 ## version 1.0.7 + - 更新分数数据 ## version 1.0.6 + - 随机一题根据竞赛分范围来获取 ## version 1.0.5 + - 获取每日一题 - 如果有竞赛分会根据竞赛分显示 绿、蓝、紫、黄、红 ## version 1.0.4 -- 修改padLevel错误 + +- 修改 padLevel 错误 - 自动化提交到市场 ## version 1.0.3 + - 题目颜色显示 ## version 1.0.2 + - 设置相关内容 ## version 1.0.1 + - 设置相关内容 diff --git a/README.md b/README.md index c97ebb1..4723698 100644 --- a/README.md +++ b/README.md @@ -11,53 +11,75 @@

# 概要设计 + - 在 VS Code 中解决 Leetcode 问题 - Leetcode 只提供了简单、中等、困难的难度区分。题目与题目之间难度差别很大,因此需要客观的分数对题目难度进行打分 - 增加中文官方的每日一题 -- 修复tag分类错误 +- 修复 tag 分类错误 - 增加精选分类 -- 增加剑指Offer、面试金典相关内容 +- 增加剑指 Offer、面试金典相关内容 - 增加一键提交全部题目测试用例功能 -- 尝试不需要额外安装node环境,使用vscode自带的node版本 -- 从[zerotrac.github.io](https://zerotrac.github.io/leetcode_problem_rating/data.json)获取数据进行缓存,数据更新时,可以尝试使用deleteAllCache,重新获取数据 +- 尝试不需要额外安装 node 环境,使用 vscode 自带的 node 版本 +- 从[zerotrac.github.io](https://zerotrac.github.io/leetcode_problem_rating/data.json)获取数据进行缓存,数据更新时,可以尝试使用 deleteAllCache,重新获取数据 +- 将所有提供的测试用例单独存放到代码下方,一键提交也会收集这部分的测试用例(简单去重()) # 关于本项目 + - [项目地址:https://github.com/ccagml/vscode-leetcode-problem-rating/](https://github.com/ccagml/vscode-leetcode-problem-rating/) - [报告问题](https://github.com/ccagml/vscode-leetcode-problem-rating/issues) - [疑难解答](https://github.com/LeetCode-OpenSource/vscode-leetcode/wiki/%E7%96%91%E9%9A%BE%E8%A7%A3%E7%AD%94) - [常见问题](https://github.com/LeetCode-OpenSource/vscode-leetcode/wiki/%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98) -- 趁着现在只有提交一个PR就能成为项目元老了 +- 趁着现在只有提交一个 PR 就能成为项目元老了 ## 快速开始 + ![quickstart](https://www.ccagml.com/wp-content/uploads/2022/10/quickstart.gif) -## tag分类 + +## tag 分类 + ![tag](https://www.ccagml.com/wp-content/uploads/2022/10/tag.gif) + ## 查询功能 + ![search](https://www.ccagml.com/wp-content/uploads/2022/10/search.gif) +## 区块测试用例 + +### 例子(cpp 文件为例) + +``` +// @lcpr case=start +// "PAYPALISHIRINGGGG"\n3\n +// @lcpr case=end +``` + +### 说明 + +- 以 @lcpr case=start 开头 +- 第二行存放原本手动填写测试用例 +- 以 @lcpr case=end 结尾 + +### 一键提交的用例去重 + +- 简单的比较这些用例字符串是否相同 -## ❗️ 注意 ❗️- 无法登录 LeetCode 节点的临时解决办法 -> 注意:如果使用的是 `leetcode.cn` 账户,可以跳过此段落。 - -近期我们发现插件出现了[无法登录 leetcode.com 节点的问题](https://github.com/LeetCode-OpenSource/vscode-leetcode/issues/478)。原因是因为近期 leetcode.com 改变了登录机制,目前我们暂时没有找到解决该问题的完美解决方案。你可以直接点击登录按钮并选择第三方登录或者 `Cookie` 登录。 -> 注意:如果你希望使用第三方登录(**推荐**),请确保你的账户已经与第三方账户连接。如果你希望通过 `Cookie` 登录,请点击[该连接](https://github.com/LeetCode-OpenSource/vscode-leetcode/issues/478#issuecomment-564757098)查看登录步骤。 - ## 运行条件 + - [VS Code 1.57.0+](https://code.visualstudio.com/) - [Node.js 10+](https://nodejs.org) - > 注意:请确保`Node`在`PATH`环境变量中。您也可以通过设定 `leetcode.nodePath` 选项来指定 `Node.js` 可执行文件的路径。 - + > 注意:请确保`Node`在`PATH`环境变量中。您也可以通过设定 `leetcode.nodePath` 选项来指定 `Node.js` 可执行文件的路径。 ## 插件配置项 @@ -70,29 +92,30 @@ | leetcode-problem-rating.endpoint | 指定使用的终端,可用终端有:`leetcode`, `leetcode-cn` | leetcode.cn | | leetcode-problem-rating.workspaceFolder | 指定保存文件的工作区目录 | `""` | | leetcode-problem-rating.filePath | 指定生成题目文件的相对文件夹路径名和文件名。点击查看[更多详细用法](https://github.com/LeetCode-OpenSource/vscode-leetcode/wiki/%E8%87%AA%E5%AE%9A%E4%B9%89%E9%A2%98%E7%9B%AE%E6%96%87%E4%BB%B6%E7%9A%84%E7%9B%B8%E5%AF%B9%E6%96%87%E4%BB%B6%E5%A4%B9%E8%B7%AF%E5%BE%84%E5%92%8C%E6%96%87%E4%BB%B6%E5%90%8D)。 | | -| leetcode-problem-rating.enableStatusBar | 指定是否在 VS Code 下方显示插件状态栏。 增加周赛分数据 | `true` | -| leetcode-problem-rating.editor.shortcuts | 指定在编辑器内所自定义的快捷方式。可用的快捷方式有: `submit`, `test`, `star`, `solution`, `description`, case, allcase 。 | ["submit, case, allcase, test, solution"] | +| leetcode-problem-rating.enableStatusBar | 指定是否在 VS Code 下方显示插件状态栏。 增加周赛分数据 | `true` | +| leetcode-problem-rating.editor.shortcuts | 指定在编辑器内所自定义的快捷方式。可用的快捷方式有: `submit`, `test`, `star`, `solution`, `description`, case, allcase 。 | ["submit, case, allcase, test, solution"] | | leetcode-problem-rating.enableSideMode | 指定在解决一道题时,是否将`问题预览`、`高票答案`与`提交结果`窗口集中在编辑器的第二栏。 | `true` | | leetcode-problem-rating.nodePath | 指定 `Node.js` 可执行文件的路径。如:C:\Program Files\nodejs\node.exe | `node` | | leetcode-problem-rating.showCommentDescription | 指定是否要在注释中显示题干。 | `false` | | leetcode-problem-rating.useEndpointTranslation | 是否显示翻译版本内容。 | `true` | -| leetcode-problem-rating.sortStrategy | 排序的选项。Acceptance Rate (Ascending):通过率递增 Acceptance Rate (Descending):通过率递减 Score (Ascending):分数递增 Score (Descending):分数递减 | None | +| leetcode-problem-rating.sortStrategy | 排序的选项。Acceptance Rate (Ascending):通过率递增 Acceptance Rate (Descending):通过率递减 Score (Ascending):分数递增 Score (Descending):分数递减 | None | | leetcode-problem-rating.pickOneByRankRangeMin | 随机一题的最小浮动,随机一题最低分(你的竞赛分+本配置)。 | 50 | | leetcode-problem-rating.pickOneByRankRangeMax | 随机一题的最大浮动,随机一题最高分(你的竞赛分+本配置)。 | 150 | | leetcode-problem-rating.hideScore | 隐藏分数相关的题目。Score:隐藏有分数的题目, NoScore:隐藏没有分数的题目, ScoreRange:隐藏分数范围外的题目 | None | -| leetcode-problem-rating.useVscodeNode | 默认情况下使用VsCode自带Node环境,不需要额外安装Node环境 | true | - - +| leetcode-problem-rating.useVscodeNode | 默认情况下使用 VsCode 自带 Node 环境,不需要额外安装 Node 环境 | true | ## 更新日志 请参考[更新日志](https://github.com/ccagml/vscode-leetcode-problem-rating/CHANGELOG.md) ## 鸣谢 + - 本插件基于[LeetCode-OpenSource](https://github.com/LeetCode-OpenSource)的[vscode-leetcode](https://github.com/LeetCode-OpenSource/vscode-leetcode/) - 题目分数数据基于[zerotrac](https://github.com/zerotrac)的[leetcode_problem_rating](https://github.com/zerotrac/leetcode_problem_rating/)每周的更新 +--> diff --git a/hot.sh b/hot.sh new file mode 100755 index 0000000..6587d21 --- /dev/null +++ b/hot.sh @@ -0,0 +1,2 @@ +rm -rf out/ +tsc -p ./ diff --git a/package-lock.json b/package-lock.json index 6cdb985..38f039a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "vscode-leetcode-problem-rating", - "version": "1.1.9", + "version": "2.1.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "vscode-leetcode-problem-rating", - "version": "1.1.9", + "version": "2.1.0", "license": "MIT", "dependencies": { "ansi-styles": "3.2.1", @@ -19,7 +19,6 @@ "mkdirp": "^1.0.4", "moment": "^2.29.1", "nconf": "^0.11.2", - "ora": "3.0.0", "prompt": "^1.2.0", "request": "2.88.0", "underscore": "1.12.1", @@ -33,11 +32,12 @@ "@types/node": "^14.14.33", "@types/vscode": "1.57.0", "@typescript-eslint/eslint-plugin": "^5.42.1", - "@typescript-eslint/parser": "^5.42.1", + "@typescript-eslint/parser": "^5.43.0", "chai": "4.2.0", "eslint": "^8.27.0", + "prettier": "^2.7.1", "tslint": "^5.20.1", - "typescript": "^4.8.4" + "typescript": "^4.9.3" }, "engines": { "vscode": "^1.57.0" @@ -78,6 +78,50 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@babel/highlight/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/@colors/colors": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", @@ -109,18 +153,6 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/@eslint/eslintrc/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, "node_modules/@humanwhocodes/config-array": { "version": "0.11.7", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.7.tgz", @@ -211,9 +243,9 @@ "dev": true }, "node_modules/@types/lodash": { - "version": "4.14.188", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.188.tgz", - "integrity": "sha512-zmEmF5OIM3rb7SbLCFYoQhO4dGt2FRM9AMkxvA3LaADOF1n8in/zGJlWji9fmafLoNyz+FoL6FE0SLtGIArD7w==", + "version": "4.14.189", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.189.tgz", + "integrity": "sha512-kb9/98N6X8gyME9Cf7YaqIMvYGnBSWqEci6tiettE6iJWH1XdJz/PO8LB0GtLCG7x8dU3KWhZT+lA1a35127tA==", "dev": true }, "node_modules/@types/markdown-it": { @@ -244,14 +276,14 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.42.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.42.1.tgz", - "integrity": "sha512-LyR6x784JCiJ1j6sH5Y0K6cdExqCCm8DJUTcwG5ThNXJj/G8o5E56u5EdG4SLy+bZAwZBswC+GYn3eGdttBVCg==", + "version": "5.43.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.43.0.tgz", + "integrity": "sha512-wNPzG+eDR6+hhW4yobEmpR36jrqqQv1vxBq5LJO3fBAktjkvekfr4BRl+3Fn1CM/A+s8/EiGUbOMDoYqWdbtXA==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "5.42.1", - "@typescript-eslint/type-utils": "5.42.1", - "@typescript-eslint/utils": "5.42.1", + "@typescript-eslint/scope-manager": "5.43.0", + "@typescript-eslint/type-utils": "5.43.0", + "@typescript-eslint/utils": "5.43.0", "debug": "^4.3.4", "ignore": "^5.2.0", "natural-compare-lite": "^1.4.0", @@ -276,45 +308,15 @@ } } }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "dev": true, - "dependencies": { - "tslib": "^1.8.1" - }, - "engines": { - "node": ">= 6" - }, - "peerDependencies": { - "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" - } - }, "node_modules/@typescript-eslint/parser": { - "version": "5.42.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.42.1.tgz", - "integrity": "sha512-kAV+NiNBWVQDY9gDJDToTE/NO8BHi4f6b7zTsVAJoTkmB/zlfOpiEVBzHOKtlgTndCKe8vj9F/PuolemZSh50Q==", + "version": "5.43.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.43.0.tgz", + "integrity": "sha512-2iHUK2Lh7PwNUlhFxxLI2haSDNyXvebBO9izhjhMoDC+S3XI9qt2DGFUsiJ89m2k7gGYch2aEpYqV5F/+nwZug==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "5.42.1", - "@typescript-eslint/types": "5.42.1", - "@typescript-eslint/typescript-estree": "5.42.1", + "@typescript-eslint/scope-manager": "5.43.0", + "@typescript-eslint/types": "5.43.0", + "@typescript-eslint/typescript-estree": "5.43.0", "debug": "^4.3.4" }, "engines": { @@ -334,13 +336,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "5.42.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.42.1.tgz", - "integrity": "sha512-QAZY/CBP1Emx4rzxurgqj3rUinfsh/6mvuKbLNMfJMMKYLRBfweus8brgXF8f64ABkIZ3zdj2/rYYtF8eiuksQ==", + "version": "5.43.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.43.0.tgz", + "integrity": "sha512-XNWnGaqAtTJsUiZaoiGIrdJYHsUOd3BZ3Qj5zKp9w6km6HsrjPk/TGZv0qMTWyWj0+1QOqpHQ2gZOLXaGA9Ekw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.42.1", - "@typescript-eslint/visitor-keys": "5.42.1" + "@typescript-eslint/types": "5.43.0", + "@typescript-eslint/visitor-keys": "5.43.0" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -351,13 +353,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "5.42.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.42.1.tgz", - "integrity": "sha512-WWiMChneex5w4xPIX56SSnQQo0tEOy5ZV2dqmj8Z371LJ0E+aymWD25JQ/l4FOuuX+Q49A7pzh/CGIQflxMVXg==", + "version": "5.43.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.43.0.tgz", + "integrity": "sha512-K21f+KY2/VvYggLf5Pk4tgBOPs2otTaIHy2zjclo7UZGLyFH86VfUOm5iq+OtDtxq/Zwu2I3ujDBykVW4Xtmtg==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "5.42.1", - "@typescript-eslint/utils": "5.42.1", + "@typescript-eslint/typescript-estree": "5.43.0", + "@typescript-eslint/utils": "5.43.0", "debug": "^4.3.4", "tsutils": "^3.21.0" }, @@ -377,25 +379,10 @@ } } }, - "node_modules/@typescript-eslint/type-utils/node_modules/tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "dev": true, - "dependencies": { - "tslib": "^1.8.1" - }, - "engines": { - "node": ">= 6" - }, - "peerDependencies": { - "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" - } - }, "node_modules/@typescript-eslint/types": { - "version": "5.42.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.42.1.tgz", - "integrity": "sha512-Qrco9dsFF5lhalz+lLFtxs3ui1/YfC6NdXu+RAGBa8uSfn01cjO7ssCsjIsUs484vny9Xm699FSKwpkCcqwWwA==", + "version": "5.43.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.43.0.tgz", + "integrity": "sha512-jpsbcD0x6AUvV7tyOlyvon0aUsQpF8W+7TpJntfCUWU1qaIKu2K34pMwQKSzQH8ORgUrGYY6pVIh1Pi8TNeteg==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -406,13 +393,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.42.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.42.1.tgz", - "integrity": "sha512-qElc0bDOuO0B8wDhhW4mYVgi/LZL+igPwXtV87n69/kYC/7NG3MES0jHxJNCr4EP7kY1XVsRy8C/u3DYeTKQmw==", + "version": "5.43.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.43.0.tgz", + "integrity": "sha512-BZ1WVe+QQ+igWal2tDbNg1j2HWUkAa+CVqdU79L4HP9izQY6CNhXfkNwd1SS4+sSZAP/EthI1uiCSY/+H0pROg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.42.1", - "@typescript-eslint/visitor-keys": "5.42.1", + "@typescript-eslint/types": "5.43.0", + "@typescript-eslint/visitor-keys": "5.43.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -432,47 +419,17 @@ } } }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "dev": true, - "dependencies": { - "tslib": "^1.8.1" - }, - "engines": { - "node": ">= 6" - }, - "peerDependencies": { - "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" - } - }, "node_modules/@typescript-eslint/utils": { - "version": "5.42.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.42.1.tgz", - "integrity": "sha512-Gxvf12xSp3iYZd/fLqiQRD4uKZjDNR01bQ+j8zvhPjpsZ4HmvEFL/tC4amGNyxN9Rq+iqvpHLhlqx6KTxz9ZyQ==", + "version": "5.43.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.43.0.tgz", + "integrity": "sha512-8nVpA6yX0sCjf7v/NDfeaOlyaIIqL7OaIGOWSPFqUKK59Gnumd3Wa+2l8oAaYO2lk0sO+SbWFWRSvhu8gLGv4A==", "dev": true, "dependencies": { "@types/json-schema": "^7.0.9", "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.42.1", - "@typescript-eslint/types": "5.42.1", - "@typescript-eslint/typescript-estree": "5.42.1", + "@typescript-eslint/scope-manager": "5.43.0", + "@typescript-eslint/types": "5.43.0", + "@typescript-eslint/typescript-estree": "5.43.0", "eslint-scope": "^5.1.1", "eslint-utils": "^3.0.0", "semver": "^7.3.7" @@ -488,28 +445,13 @@ "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/@typescript-eslint/utils/node_modules/semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.42.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.42.1.tgz", - "integrity": "sha512-LOQtSF4z+hejmpUvitPlc4hA7ERGoj2BVkesOcG91HCn8edLGUXbTrErmutmPbl8Bo9HjAvOO/zBKQHExXNA2A==", + "version": "5.43.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.43.0.tgz", + "integrity": "sha512-icl1jNH/d18OVHLfcwdL3bWUKsBeIiKYTGxMJCoGe7xFht+E4QgzOqoWYrU8XSLJWhVw8nTacbm03v23J/hFTg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.42.1", + "@typescript-eslint/types": "5.43.0", "eslint-visitor-keys": "^3.3.0" }, "engines": { @@ -557,11 +499,11 @@ } }, "node_modules/ansi-regex": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", - "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "engines": { - "node": ">=4" + "node": ">=8" } }, "node_modules/ansi-styles": { @@ -719,18 +661,54 @@ } }, "node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=4" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/chalk/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/chalk/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/chalk/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, "node_modules/check-error": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", @@ -776,25 +754,6 @@ "url": "https://github.com/sponsors/fb55" } }, - "node_modules/cli-cursor": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", - "integrity": "sha512-8lgKz8LmCRYZZQDpRyT2m5rKJ08TnU4tR9FFFW2rxpxR1FzWi4PQ/NfyODchAatHaUgnSPVcx/R5w6NuTBzFiw==", - "dependencies": { - "restore-cursor": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/cli-spinners": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-1.3.1.tgz", - "integrity": "sha512-1QL4544moEsDVH9T/l6Cemov/37iv1RtoKf7NJ04A60+4MREXNfx/QvavbH6QoGdsD4N4Mwy49cmaINR/o2mdg==", - "engines": { - "node": ">=4" - } - }, "node_modules/cliui": { "version": "7.0.4", "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", @@ -805,33 +764,6 @@ "wrap-ansi": "^7.0.0" } }, - "node_modules/cliui/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "engines": { - "node": ">=8" - } - }, - "node_modules/cliui/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", - "engines": { - "node": ">=0.8" - } - }, "node_modules/color-convert": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", @@ -975,17 +907,6 @@ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true }, - "node_modules/defaults": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", - "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", - "dependencies": { - "clone": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -1112,11 +1033,15 @@ } }, "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, "engines": { - "node": ">=0.8.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/eslint": { @@ -1224,76 +1149,6 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, - "node_modules/eslint/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/eslint/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/eslint/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/eslint/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/eslint/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/eslint/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/eslint/node_modules/eslint-scope": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", @@ -1316,51 +1171,6 @@ "node": ">=4.0" } }, - "node_modules/eslint/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/eslint/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/eslint/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/eslint/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/espree": { "version": "9.4.1", "resolved": "https://registry.npmjs.org/espree/-/espree-9.4.1.tgz", @@ -1688,9 +1498,9 @@ } }, "node_modules/globals": { - "version": "13.17.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.17.0.tgz", - "integrity": "sha512-1C+6nQRb1GwGMKm2dH/E7enFAMxGTmGI7/dEdhy/DNelv85w9B72t3uc5frtMNXIbzrarJJ/lTCjcaZwbLJmyw==", + "version": "13.18.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.18.0.tgz", + "integrity": "sha512-/mR4KI8Ps2spmoc0Ulu9L7agOF0du1CZNQ3dke8yItYlyKNmGrkONemBbd6V8UTc1Wgcqn21t3WYB7dbRmh6/A==", "dev": true, "dependencies": { "type-fest": "^0.20.2" @@ -1767,11 +1577,12 @@ } }, "node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, "engines": { - "node": ">=4" + "node": ">=8" } }, "node_modules/he": { @@ -1968,27 +1779,17 @@ "dev": true }, "node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" + "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, - "node_modules/js-yaml/node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, "node_modules/jsbn": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", @@ -2083,20 +1884,9 @@ }, "node_modules/lodash.merge": { "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true - }, - "node_modules/log-symbols": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", - "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", - "dependencies": { - "chalk": "^2.0.1" - }, - "engines": { - "node": ">=4" - } + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true }, "node_modules/lru-cache": { "version": "6.0.0", @@ -2179,14 +1969,6 @@ "node": ">= 0.6" } }, - "node_modules/mimic-fn": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", - "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", - "engines": { - "node": ">=4" - } - }, "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -2292,17 +2074,6 @@ "wrappy": "1" } }, - "node_modules/onetime": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", - "integrity": "sha512-oyyPpiMaKARvvcgip+JV+7zci5L8D1W9RZIz2l1o08AM3pfspitVWnPt3mzHcBPp12oYMTy0pqrFs/C+m3EwsQ==", - "dependencies": { - "mimic-fn": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/optionator": { "version": "0.9.1", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", @@ -2320,22 +2091,6 @@ "node": ">= 0.8.0" } }, - "node_modules/ora": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ora/-/ora-3.0.0.tgz", - "integrity": "sha512-LBS97LFe2RV6GJmXBi6OKcETKyklHNMV0xw7BtsVn2MlsgsydyZetSCbCANr+PFLmDyv4KV88nn0eCKza665Mg==", - "dependencies": { - "chalk": "^2.3.1", - "cli-cursor": "^2.1.0", - "cli-spinners": "^1.1.0", - "log-symbols": "^2.2.0", - "strip-ansi": "^4.0.0", - "wcwidth": "^1.0.1" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", @@ -2478,6 +2233,21 @@ "node": ">= 0.8.0" } }, + "node_modules/prettier": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz", + "integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==", + "dev": true, + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, "node_modules/prompt": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/prompt/-/prompt-1.3.0.tgz", @@ -2624,18 +2394,6 @@ "node": ">=4" } }, - "node_modules/restore-cursor": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", - "integrity": "sha512-6IzJLuGi4+R14vwagDHX+JrXmPVtPpn4mffDJ1UdR7/Edm87fl6yi8mMBIVvFtJaNTUvjughmW4hwLhRG7gC1Q==", - "dependencies": { - "onetime": "^2.0.0", - "signal-exit": "^3.0.2" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", @@ -2722,12 +2480,18 @@ "integrity": "sha512-nZi59hW3Sl5P3+wOO89eHBAAGwmCPd2aE1+dLZV5MO+ItQctIvAqihzaAXIQhvtH4KJPxM080HsnqltR2y8cWg==" }, "node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, "bin": { - "semver": "bin/semver" + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" } }, "node_modules/shebang-command": { @@ -2751,11 +2515,6 @@ "node": ">=8" } }, - "node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" - }, "node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", @@ -2816,39 +2575,20 @@ "node": ">=8" } }, - "node_modules/string-width/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "engines": { - "node": ">=8" - } - }, - "node_modules/string-width/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/string.fromcodepoint": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/string.fromcodepoint/-/string.fromcodepoint-0.2.1.tgz", "integrity": "sha512-n69H31OnxSGSZyZbgBlvYIXlrMhJQ0dQAX1js1QDhpaUH6zmU3QYlj07bCwCNlPOu3oRXIubGPl2gDGnHsiCqg==" }, "node_modules/strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dependencies": { - "ansi-regex": "^3.0.0" + "ansi-regex": "^5.0.1" }, "engines": { - "node": ">=4" + "node": ">=8" } }, "node_modules/strip-json-comments": { @@ -2864,14 +2604,15 @@ } }, "node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, "dependencies": { - "has-flag": "^3.0.0" + "has-flag": "^4.0.0" }, "engines": { - "node": ">=4" + "node": ">=8" } }, "node_modules/supports-preserve-symlinks-flag": { @@ -2952,6 +2693,60 @@ "typescript": ">=2.3.0-dev || >=2.4.0-dev || >=2.5.0-dev || >=2.6.0-dev || >=2.7.0-dev || >=2.8.0-dev || >=2.9.0-dev || >=3.0.0-dev || >= 3.1.0-dev || >= 3.2.0-dev" } }, + "node_modules/tslint/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/tslint/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/tslint/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/tslint/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/tslint/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, "node_modules/tslint/node_modules/mkdirp": { "version": "0.5.6", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", @@ -2964,7 +2759,28 @@ "mkdirp": "bin/cmd.js" } }, - "node_modules/tsutils": { + "node_modules/tslint/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/tslint/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/tslint/node_modules/tsutils": { "version": "2.29.0", "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==", @@ -2976,6 +2792,21 @@ "typescript": ">=2.1.0 || >=2.1.0-dev || >=2.2.0-dev || >=2.3.0-dev || >=2.4.0-dev || >=2.5.0-dev || >=2.6.0-dev || >=2.7.0-dev || >=2.8.0-dev || >=2.9.0-dev || >= 3.0.0-dev || >= 3.1.0-dev" } }, + "node_modules/tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "dependencies": { + "tslib": "^1.8.1" + }, + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" + } + }, "node_modules/tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", @@ -3026,9 +2857,9 @@ } }, "node_modules/typescript": { - "version": "4.8.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.4.tgz", - "integrity": "sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==", + "version": "4.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.3.tgz", + "integrity": "sha512-CIfGzTelbKNEnLpLdGFgdyKhG23CKdKgQPOBc+OUNrkJ2vr+KSzsSV5kq5iWhEQbok+quxgGzrAtGWCyU7tHnA==", "dev": true, "bin": { "tsc": "bin/tsc", @@ -3102,14 +2933,6 @@ "extsprintf": "^1.2.0" } }, - "node_modules/wcwidth": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", - "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", - "dependencies": { - "defaults": "^1.0.3" - } - }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -3126,11 +2949,11 @@ } }, "node_modules/winston": { - "version": "2.4.6", - "resolved": "https://registry.npmjs.org/winston/-/winston-2.4.6.tgz", - "integrity": "sha512-J5Zu4p0tojLde8mIOyDSsmLmcP8I3Z6wtwpTDHx1+hGcdhxcJaAmG4CFtagkb+NiN1M9Ek4b42pzMWqfc9jm8w==", + "version": "2.4.7", + "resolved": "https://registry.npmjs.org/winston/-/winston-2.4.7.tgz", + "integrity": "sha512-vLB4BqzCKDnnZH9PHGoS2ycawueX4HLqENXQitvFHczhgW2vFpSOn31LZtVr1KU8YTw7DS4tM+cqyovxo8taVg==", "dependencies": { - "async": "^3.2.3", + "async": "^2.6.4", "colors": "1.0.x", "cycle": "1.0.x", "eyes": "0.1.x", @@ -3142,9 +2965,12 @@ } }, "node_modules/winston/node_modules/async": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", - "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==" + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", + "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", + "dependencies": { + "lodash": "^4.17.14" + } }, "node_modules/word-wrap": { "version": "1.2.3", @@ -3176,14 +3002,6 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/wrap-ansi/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "engines": { - "node": ">=8" - } - }, "node_modules/wrap-ansi/node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -3214,17 +3032,6 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, - "node_modules/wrap-ansi/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -3308,6 +3115,40 @@ "@babel/helper-validator-identifier": "^7.18.6", "chalk": "^2.0.0", "js-tokens": "^4.0.0" + }, + "dependencies": { + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } } }, "@colors/colors": { @@ -3330,17 +3171,6 @@ "js-yaml": "^4.1.0", "minimatch": "^3.1.2", "strip-json-comments": "^3.1.1" - }, - "dependencies": { - "js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "requires": { - "argparse": "^2.0.1" - } - } } }, "@humanwhocodes/config-array": { @@ -3414,9 +3244,9 @@ "dev": true }, "@types/lodash": { - "version": "4.14.188", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.188.tgz", - "integrity": "sha512-zmEmF5OIM3rb7SbLCFYoQhO4dGt2FRM9AMkxvA3LaADOF1n8in/zGJlWji9fmafLoNyz+FoL6FE0SLtGIArD7w==", + "version": "4.14.189", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.189.tgz", + "integrity": "sha512-kb9/98N6X8gyME9Cf7YaqIMvYGnBSWqEci6tiettE6iJWH1XdJz/PO8LB0GtLCG7x8dU3KWhZT+lA1a35127tA==", "dev": true }, "@types/markdown-it": { @@ -3447,162 +3277,100 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "5.42.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.42.1.tgz", - "integrity": "sha512-LyR6x784JCiJ1j6sH5Y0K6cdExqCCm8DJUTcwG5ThNXJj/G8o5E56u5EdG4SLy+bZAwZBswC+GYn3eGdttBVCg==", + "version": "5.43.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.43.0.tgz", + "integrity": "sha512-wNPzG+eDR6+hhW4yobEmpR36jrqqQv1vxBq5LJO3fBAktjkvekfr4BRl+3Fn1CM/A+s8/EiGUbOMDoYqWdbtXA==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "5.42.1", - "@typescript-eslint/type-utils": "5.42.1", - "@typescript-eslint/utils": "5.42.1", + "@typescript-eslint/scope-manager": "5.43.0", + "@typescript-eslint/type-utils": "5.43.0", + "@typescript-eslint/utils": "5.43.0", "debug": "^4.3.4", "ignore": "^5.2.0", "natural-compare-lite": "^1.4.0", "regexpp": "^3.2.0", "semver": "^7.3.7", "tsutils": "^3.21.0" - }, - "dependencies": { - "semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - }, - "tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "dev": true, - "requires": { - "tslib": "^1.8.1" - } - } } }, "@typescript-eslint/parser": { - "version": "5.42.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.42.1.tgz", - "integrity": "sha512-kAV+NiNBWVQDY9gDJDToTE/NO8BHi4f6b7zTsVAJoTkmB/zlfOpiEVBzHOKtlgTndCKe8vj9F/PuolemZSh50Q==", + "version": "5.43.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.43.0.tgz", + "integrity": "sha512-2iHUK2Lh7PwNUlhFxxLI2haSDNyXvebBO9izhjhMoDC+S3XI9qt2DGFUsiJ89m2k7gGYch2aEpYqV5F/+nwZug==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "5.42.1", - "@typescript-eslint/types": "5.42.1", - "@typescript-eslint/typescript-estree": "5.42.1", + "@typescript-eslint/scope-manager": "5.43.0", + "@typescript-eslint/types": "5.43.0", + "@typescript-eslint/typescript-estree": "5.43.0", "debug": "^4.3.4" } }, "@typescript-eslint/scope-manager": { - "version": "5.42.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.42.1.tgz", - "integrity": "sha512-QAZY/CBP1Emx4rzxurgqj3rUinfsh/6mvuKbLNMfJMMKYLRBfweus8brgXF8f64ABkIZ3zdj2/rYYtF8eiuksQ==", + "version": "5.43.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.43.0.tgz", + "integrity": "sha512-XNWnGaqAtTJsUiZaoiGIrdJYHsUOd3BZ3Qj5zKp9w6km6HsrjPk/TGZv0qMTWyWj0+1QOqpHQ2gZOLXaGA9Ekw==", "dev": true, "requires": { - "@typescript-eslint/types": "5.42.1", - "@typescript-eslint/visitor-keys": "5.42.1" + "@typescript-eslint/types": "5.43.0", + "@typescript-eslint/visitor-keys": "5.43.0" } }, "@typescript-eslint/type-utils": { - "version": "5.42.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.42.1.tgz", - "integrity": "sha512-WWiMChneex5w4xPIX56SSnQQo0tEOy5ZV2dqmj8Z371LJ0E+aymWD25JQ/l4FOuuX+Q49A7pzh/CGIQflxMVXg==", + "version": "5.43.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.43.0.tgz", + "integrity": "sha512-K21f+KY2/VvYggLf5Pk4tgBOPs2otTaIHy2zjclo7UZGLyFH86VfUOm5iq+OtDtxq/Zwu2I3ujDBykVW4Xtmtg==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "5.42.1", - "@typescript-eslint/utils": "5.42.1", + "@typescript-eslint/typescript-estree": "5.43.0", + "@typescript-eslint/utils": "5.43.0", "debug": "^4.3.4", "tsutils": "^3.21.0" - }, - "dependencies": { - "tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "dev": true, - "requires": { - "tslib": "^1.8.1" - } - } } }, "@typescript-eslint/types": { - "version": "5.42.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.42.1.tgz", - "integrity": "sha512-Qrco9dsFF5lhalz+lLFtxs3ui1/YfC6NdXu+RAGBa8uSfn01cjO7ssCsjIsUs484vny9Xm699FSKwpkCcqwWwA==", + "version": "5.43.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.43.0.tgz", + "integrity": "sha512-jpsbcD0x6AUvV7tyOlyvon0aUsQpF8W+7TpJntfCUWU1qaIKu2K34pMwQKSzQH8ORgUrGYY6pVIh1Pi8TNeteg==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "5.42.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.42.1.tgz", - "integrity": "sha512-qElc0bDOuO0B8wDhhW4mYVgi/LZL+igPwXtV87n69/kYC/7NG3MES0jHxJNCr4EP7kY1XVsRy8C/u3DYeTKQmw==", + "version": "5.43.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.43.0.tgz", + "integrity": "sha512-BZ1WVe+QQ+igWal2tDbNg1j2HWUkAa+CVqdU79L4HP9izQY6CNhXfkNwd1SS4+sSZAP/EthI1uiCSY/+H0pROg==", "dev": true, "requires": { - "@typescript-eslint/types": "5.42.1", - "@typescript-eslint/visitor-keys": "5.42.1", + "@typescript-eslint/types": "5.43.0", + "@typescript-eslint/visitor-keys": "5.43.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - }, - "dependencies": { - "semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - }, - "tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "dev": true, - "requires": { - "tslib": "^1.8.1" - } - } + "semver": "^7.3.7", + "tsutils": "^3.21.0" } }, "@typescript-eslint/utils": { - "version": "5.42.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.42.1.tgz", - "integrity": "sha512-Gxvf12xSp3iYZd/fLqiQRD4uKZjDNR01bQ+j8zvhPjpsZ4HmvEFL/tC4amGNyxN9Rq+iqvpHLhlqx6KTxz9ZyQ==", + "version": "5.43.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.43.0.tgz", + "integrity": "sha512-8nVpA6yX0sCjf7v/NDfeaOlyaIIqL7OaIGOWSPFqUKK59Gnumd3Wa+2l8oAaYO2lk0sO+SbWFWRSvhu8gLGv4A==", "dev": true, "requires": { "@types/json-schema": "^7.0.9", "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.42.1", - "@typescript-eslint/types": "5.42.1", - "@typescript-eslint/typescript-estree": "5.42.1", + "@typescript-eslint/scope-manager": "5.43.0", + "@typescript-eslint/types": "5.43.0", + "@typescript-eslint/typescript-estree": "5.43.0", "eslint-scope": "^5.1.1", "eslint-utils": "^3.0.0", "semver": "^7.3.7" - }, - "dependencies": { - "semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - } } }, "@typescript-eslint/visitor-keys": { - "version": "5.42.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.42.1.tgz", - "integrity": "sha512-LOQtSF4z+hejmpUvitPlc4hA7ERGoj2BVkesOcG91HCn8edLGUXbTrErmutmPbl8Bo9HjAvOO/zBKQHExXNA2A==", + "version": "5.43.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.43.0.tgz", + "integrity": "sha512-icl1jNH/d18OVHLfcwdL3bWUKsBeIiKYTGxMJCoGe7xFht+E4QgzOqoWYrU8XSLJWhVw8nTacbm03v23J/hFTg==", "dev": true, "requires": { - "@typescript-eslint/types": "5.42.1", + "@typescript-eslint/types": "5.43.0", "eslint-visitor-keys": "^3.3.0" } }, @@ -3631,9 +3399,9 @@ } }, "ansi-regex": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", - "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==" + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" }, "ansi-styles": { "version": "3.2.1", @@ -3763,13 +3531,39 @@ } }, "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + } } }, "check-error": { @@ -3805,19 +3599,6 @@ "domutils": "^3.0.1" } }, - "cli-cursor": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", - "integrity": "sha512-8lgKz8LmCRYZZQDpRyT2m5rKJ08TnU4tR9FFFW2rxpxR1FzWi4PQ/NfyODchAatHaUgnSPVcx/R5w6NuTBzFiw==", - "requires": { - "restore-cursor": "^2.0.0" - } - }, - "cli-spinners": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-1.3.1.tgz", - "integrity": "sha512-1QL4544moEsDVH9T/l6Cemov/37iv1RtoKf7NJ04A60+4MREXNfx/QvavbH6QoGdsD4N4Mwy49cmaINR/o2mdg==" - }, "cliui": { "version": "7.0.4", "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", @@ -3826,28 +3607,8 @@ "string-width": "^4.2.0", "strip-ansi": "^6.0.0", "wrap-ansi": "^7.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" - }, - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "requires": { - "ansi-regex": "^5.0.1" - } - } } }, - "clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==" - }, "color-convert": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", @@ -3956,14 +3717,6 @@ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true }, - "defaults": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", - "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", - "requires": { - "clone": "^1.0.2" - } - }, "delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -4051,9 +3804,10 @@ "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==" }, "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==" + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true }, "eslint": { "version": "8.27.0", @@ -4102,52 +3856,6 @@ "text-table": "^0.2.0" }, "dependencies": { - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true - }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true - }, "eslint-scope": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", @@ -4163,39 +3871,6 @@ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "requires": { - "argparse": "^2.0.1" - } - }, - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.1" - } - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } } } }, @@ -4483,9 +4158,9 @@ } }, "globals": { - "version": "13.17.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.17.0.tgz", - "integrity": "sha512-1C+6nQRb1GwGMKm2dH/E7enFAMxGTmGI7/dEdhy/DNelv85w9B72t3uc5frtMNXIbzrarJJ/lTCjcaZwbLJmyw==", + "version": "13.18.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.18.0.tgz", + "integrity": "sha512-/mR4KI8Ps2spmoc0Ulu9L7agOF0du1CZNQ3dke8yItYlyKNmGrkONemBbd6V8UTc1Wgcqn21t3WYB7dbRmh6/A==", "dev": true, "requires": { "type-fest": "^0.20.2" @@ -4540,9 +4215,10 @@ } }, "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==" + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true }, "he": { "version": "1.2.0", @@ -4688,24 +4364,12 @@ "dev": true }, "js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "dependencies": { - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "requires": { - "sprintf-js": "~1.0.2" - } - } + "argparse": "^2.0.1" } }, "jsbn": { @@ -4792,14 +4456,6 @@ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, - "log-symbols": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", - "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", - "requires": { - "chalk": "^2.0.1" - } - }, "lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", @@ -4862,11 +4518,6 @@ "mime-db": "1.52.0" } }, - "mimic-fn": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", - "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==" - }, "minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -4948,14 +4599,6 @@ "wrappy": "1" } }, - "onetime": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", - "integrity": "sha512-oyyPpiMaKARvvcgip+JV+7zci5L8D1W9RZIz2l1o08AM3pfspitVWnPt3mzHcBPp12oYMTy0pqrFs/C+m3EwsQ==", - "requires": { - "mimic-fn": "^1.0.0" - } - }, "optionator": { "version": "0.9.1", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", @@ -4970,19 +4613,6 @@ "word-wrap": "^1.2.3" } }, - "ora": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ora/-/ora-3.0.0.tgz", - "integrity": "sha512-LBS97LFe2RV6GJmXBi6OKcETKyklHNMV0xw7BtsVn2MlsgsydyZetSCbCANr+PFLmDyv4KV88nn0eCKza665Mg==", - "requires": { - "chalk": "^2.3.1", - "cli-cursor": "^2.1.0", - "cli-spinners": "^1.1.0", - "log-symbols": "^2.2.0", - "strip-ansi": "^4.0.0", - "wcwidth": "^1.0.1" - } - }, "p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", @@ -5080,6 +4710,12 @@ "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true }, + "prettier": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz", + "integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==", + "dev": true + }, "prompt": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/prompt/-/prompt-1.3.0.tgz", @@ -5183,15 +4819,6 @@ "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true }, - "restore-cursor": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", - "integrity": "sha512-6IzJLuGi4+R14vwagDHX+JrXmPVtPpn4mffDJ1UdR7/Edm87fl6yi8mMBIVvFtJaNTUvjughmW4hwLhRG7gC1Q==", - "requires": { - "onetime": "^2.0.0", - "signal-exit": "^3.0.2" - } - }, "reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", @@ -5237,10 +4864,13 @@ "integrity": "sha512-nZi59hW3Sl5P3+wOO89eHBAAGwmCPd2aE1+dLZV5MO+ItQctIvAqihzaAXIQhvtH4KJPxM080HsnqltR2y8cWg==" }, "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } }, "shebang-command": { "version": "2.0.0", @@ -5257,11 +4887,6 @@ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true }, - "signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" - }, "slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", @@ -5303,21 +4928,6 @@ "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" - }, - "dependencies": { - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" - }, - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "requires": { - "ansi-regex": "^5.0.1" - } - } } }, "string.fromcodepoint": { @@ -5326,11 +4936,11 @@ "integrity": "sha512-n69H31OnxSGSZyZbgBlvYIXlrMhJQ0dQAX1js1QDhpaUH6zmU3QYlj07bCwCNlPOu3oRXIubGPl2gDGnHsiCqg==" }, "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "requires": { - "ansi-regex": "^3.0.0" + "ansi-regex": "^5.0.1" } }, "strip-json-comments": { @@ -5340,11 +4950,12 @@ "dev": true }, "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, "requires": { - "has-flag": "^3.0.0" + "has-flag": "^4.0.0" } }, "supports-preserve-symlinks-flag": { @@ -5404,6 +5015,48 @@ "tsutils": "^2.29.0" }, "dependencies": { + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true + }, + "js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, "mkdirp": { "version": "0.5.6", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", @@ -5412,13 +5065,37 @@ "requires": { "minimist": "^1.2.6" } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "tsutils": { + "version": "2.29.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", + "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==", + "dev": true, + "requires": { + "tslib": "^1.8.1" + } } } }, "tsutils": { - "version": "2.29.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", - "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==", + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", "dev": true, "requires": { "tslib": "^1.8.1" @@ -5459,9 +5136,9 @@ "dev": true }, "typescript": { - "version": "4.8.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.4.tgz", - "integrity": "sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==", + "version": "4.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.3.tgz", + "integrity": "sha512-CIfGzTelbKNEnLpLdGFgdyKhG23CKdKgQPOBc+OUNrkJ2vr+KSzsSV5kq5iWhEQbok+quxgGzrAtGWCyU7tHnA==", "dev": true }, "uc.micro": { @@ -5517,14 +5194,6 @@ "extsprintf": "^1.2.0" } }, - "wcwidth": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", - "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", - "requires": { - "defaults": "^1.0.3" - } - }, "which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -5535,11 +5204,11 @@ } }, "winston": { - "version": "2.4.6", - "resolved": "https://registry.npmjs.org/winston/-/winston-2.4.6.tgz", - "integrity": "sha512-J5Zu4p0tojLde8mIOyDSsmLmcP8I3Z6wtwpTDHx1+hGcdhxcJaAmG4CFtagkb+NiN1M9Ek4b42pzMWqfc9jm8w==", + "version": "2.4.7", + "resolved": "https://registry.npmjs.org/winston/-/winston-2.4.7.tgz", + "integrity": "sha512-vLB4BqzCKDnnZH9PHGoS2ycawueX4HLqENXQitvFHczhgW2vFpSOn31LZtVr1KU8YTw7DS4tM+cqyovxo8taVg==", "requires": { - "async": "^3.2.3", + "async": "^2.6.4", "colors": "1.0.x", "cycle": "1.0.x", "eyes": "0.1.x", @@ -5548,9 +5217,12 @@ }, "dependencies": { "async": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", - "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==" + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", + "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", + "requires": { + "lodash": "^4.17.14" + } } } }, @@ -5575,11 +5247,6 @@ "strip-ansi": "^6.0.0" }, "dependencies": { - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" - }, "ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -5600,14 +5267,6 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "requires": { - "ansi-regex": "^5.0.1" - } } } }, diff --git a/package.json b/package.json index ceb8cdb..b49e4c3 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "vscode-leetcode-problem-rating", "displayName": "LeetCode problem rating", "description": "为LeetCode题目难度进行打分。避免只有简单、中等、困难三种难度", - "version": "2.0.0", + "version": "2.1.0", "author": "ccagml", "publisher": "ccagml", "license": "MIT", @@ -769,11 +769,12 @@ "@types/node": "^14.14.33", "@types/vscode": "1.57.0", "@typescript-eslint/eslint-plugin": "^5.42.1", - "@typescript-eslint/parser": "^5.42.1", + "@typescript-eslint/parser": "^5.43.0", "chai": "4.2.0", "eslint": "^8.27.0", + "prettier": "^2.7.1", "tslint": "^5.20.1", - "typescript": "^4.8.4" + "typescript": "^4.9.3" }, "dependencies": { "ansi-styles": "3.2.1", @@ -786,7 +787,6 @@ "mkdirp": "^1.0.4", "moment": "^2.29.1", "nconf": "^0.11.2", - "ora": "3.0.0", "prompt": "^1.2.0", "request": "2.88.0", "underscore": "1.12.1", diff --git a/resources/bin/leetcode b/resources/bin/leetcode index eab3991..02f42bd 100755 --- a/resources/bin/leetcode +++ b/resources/bin/leetcode @@ -1,3 +1,3 @@ #!/usr/bin/env node -require('../../out/src/childProcessCall/cli'); +require("../../out/src/childProcessCall/childMain"); diff --git a/resources/templates/codeonly.tpl b/resources/templates/codeonly.tpl index ae5b54a..1043500 100644 --- a/resources/templates/codeonly.tpl +++ b/resources/templates/codeonly.tpl @@ -1,9 +1,20 @@ -${comment.start} -${comment.line} @lc app=${app} id=${fid} lang=${lang} -${comment.line} -${comment.line} [${fid}] ${name} -${comment.end} +<%=comment.start%> +<%=comment.line%> @lc app=<%=app%> id=<%=fid%> lang=<%=lang%> +<%=comment.line%> @lcpr version=<%=LCPTCTX.version%> +<%=comment.line%> +<%=comment.line%> [<%=fid%>] <%=name%> +<%=comment.end%> -${comment.singleLine} @lc code=start -${code} -${comment.singleLine} @lc code=end +<%=comment.singleLine%> @lc code=start +<%=code%> +<%=comment.singleLine%> @lc code=end + + +<% if(allCaseList && allCaseList.length > 0){ %> +<%=comment.start%><% allCaseList.forEach(function(acase) { %> +<%=comment.singleLine%> @lcpr case=start +<%=comment.singleLine%> <% acase.forEach(function(a_caseitem) { %><%=a_caseitem%>\n<% }) %> +<%=comment.singleLine%> @lcpr case=end +<% }) %> +<%=comment.end%> +<% } %> diff --git a/resources/templates/detailed.tpl b/resources/templates/detailed.tpl index 7329a7d..d004de7 100644 --- a/resources/templates/detailed.tpl +++ b/resources/templates/detailed.tpl @@ -1,21 +1,31 @@ -${comment.start} -${comment.line} @lc app=${app} id=${fid} lang=${lang} -${comment.line} -${comment.line} [${fid}] ${name} -${comment.line} -${comment.line} ${link} -${comment.line} -${comment.line} ${category} -${comment.line} ${level} (${percent}%) -${comment.line} Likes: ${likes} -${comment.line} Dislikes: ${dislikes} -${comment.line} Total Accepted: ${totalAC} -${comment.line} Total Submissions: ${totalSubmit} -${comment.line} Testcase Example: ${testcase} -${comment.line} -{{ desc.forEach(function(x) { }}${comment.line} ${x} -{{ }) }}${comment.end} +<%=comment.start%> +<%=comment.line%> @lc app=<%=app%> id=<%=fid%> lang=<%=lang%> +<%=comment.line%> @lcpr version=<%=LCPTCTX.version%> +<%=comment.line%> +<%=comment.line%> [<%=fid%>] <%=name%> +<%=comment.line%> +<%=comment.line%> <%=link%> +<%=comment.line%> +<%=comment.line%> <%=category%> +<%=comment.line%> <%=level%> (<%=percent%>%) +<%=comment.line%> Likes: <%=likes%> +<%=comment.line%> Dislikes: <%=dislikes%> +<%=comment.line%> Total Accepted: <%=totalAC%> +<%=comment.line%> Total Submissions: <%=totalSubmit%> +<%=comment.line%> Testcase Example: <%=testcase%> +<%=comment.line%> +<% desc.forEach(function(x) { %><%=comment.line%> <%=x%> +<% }) %><%=comment.end%> -${comment.singleLine} @lc code=start -${code} -${comment.singleLine} @lc code=end +<%=comment.singleLine%> @lc code=start +<%=code%> +<%=comment.singleLine%> @lc code=end + +<% if(allCaseList && allCaseList.length > 0){ %> +<%=comment.start%><% allCaseList.forEach(function(acase) { %> +<%=comment.singleLine%> @lcpr case=start +<%=comment.singleLine%> <% acase.forEach(function(a_caseitem) { %><%=a_caseitem%>\n<% }) %> +<%=comment.singleLine%> @lcpr case=end +<% }) %> +<%=comment.end%> +<% } %> diff --git a/src/childProcessCall/cli.ts b/src/childProcessCall/cli.ts deleted file mode 100644 index 5cba554..0000000 --- a/src/childProcessCall/cli.ts +++ /dev/null @@ -1,41 +0,0 @@ - -/* - * Filename: https://github.com/ccagml/vscode-leetcode-problem-rating/src/childProcessCall/cli.ts - * Path: https://github.com/ccagml/vscode-leetcode-problem-rating - * Created Date: Thursday, October 27th 2022, 7:43:29 pm - * Author: ccagml - * - * Copyright (c) 2022 ccagml . All rights reserved. - */ -// var h = require('./helper'); - - -import { myPluginBase } from "./my_plugin_base"; -import { config } from "./config"; -import { log } from "./log"; -import { storageUtils } from "./storageUtils"; -class NewCli { - constructor() { - this.run(); - } - public run() { - process.stdout.on('error', function (e) { - if (e.code === 'EPIPE') process.exit(); - }); - config.init(); - log.init(); - storageUtils.init(); - if (myPluginBase.base_init()) { - myPluginBase.save(); - storageUtils.initCache(); - this.runCommand_new(); - } - }; - private runCommand_new() { - let com_str = process.argv[2]; - let auto_js = require("./commands/" + com_str)[com_str + "Command"]; - auto_js.handler(auto_js.process_argv(process.argv)); - } -} - -export const newCli: NewCli = new NewCli(); diff --git a/src/childProcessCall/commands/cache.ts b/src/childProcessCall/commands/cache.ts deleted file mode 100644 index f8fb0ec..0000000 --- a/src/childProcessCall/commands/cache.ts +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Filename: https://github.com/ccagml/vscode-leetcode-problem-rating/src/childProcessCall/commands/cache.ts - * Path: https://github.com/ccagml/vscode-leetcode-problem-rating - * Created Date: Thursday, October 27th 2022, 7:43:29 pm - * Author: ccagml - * - * Copyright (c) 2022 ccagml . All rights reserved. - */ - - -// let underscore = require('underscore'); - - -import { helper } from "../helper"; -// import { log } from "../log"; -import { storageUtils } from "../storageUtils"; -import { session } from "../session"; - -class CacheCommand { - constructor() { - } - - process_argv = function (argv) { - let argv_config = helper.base_argv().option('d', { - alias: 'delete', - type: 'boolean', - describe: 'Delete cache by keyword', - default: false - }); - argv_config.process_argv(argv); - - return argv_config.get_result(); - }; - - - handler = function (argv) { - session.argv = argv; - - const name = argv.keyword; - const isInteger = Number.isInteger(Number(name)); - - const all_data_file = storageUtils.listCache() - .filter(function (f) { - return (name.length === 0) || - (isInteger ? f.name.startsWith(name + '.') : f.name === name); - }); - - if (argv.delete) { - for (let f of all_data_file) { - storageUtils.delCache(f.name); - } - } - }; -} - -export const cacheCommand: CacheCommand = new CacheCommand(); diff --git a/src/childProcessCall/commands/config.ts b/src/childProcessCall/commands/config.ts deleted file mode 100644 index 9936333..0000000 --- a/src/childProcessCall/commands/config.ts +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Filename: https://github.com/ccagml/vscode-leetcode-problem-rating/src/childProcessCall/commands/config.ts - * Path: https://github.com/ccagml/vscode-leetcode-problem-rating - * Created Date: Thursday, October 27th 2022, 7:43:29 pm - * Author: ccagml - * - * Copyright (c) 2022 ccagml . All rights reserved. - */ - - -// let underscore = require('underscore'); -// let nconf = require('nconf'); - - -// import { config } from "../config"; -// import { log } from "../log"; -// import { file } from "../file"; -// import { session } from "../session"; -// import { helper } from "../helper"; - -class ConfigCommand { - constructor() { - - } - - // process_argv(argv) { - // let argv_config = helper.base_argv().option('a', { - // alias: 'all', - // type: 'boolean', - // describe: 'Show all config', - // default: false - // }) - // .option('d', { - // alias: 'delete', - // type: 'boolean', - // describe: 'Delete config by key', - // default: false - // }) - // .positional('key', { - // type: 'string', - // describe: 'Config key, delimited by colon', - // default: '' - // }) - // .positional('value', { - // type: 'string', - // describe: 'Config value', - // default: '' - // }); - // argv_config.process_argv(argv); - - // return argv_config.get_result(); - // } - - - // prettyConfig(cfg) { - // return JSON.stringify(cfg, null, 2); - // } - - // loadConfig(showall) { - // const cfg = showall ? config.getAll(true) : nconf.get(); - // return underscore.omit(cfg, 'type'); - // } - - // saveConfig() { - // storageUtils.write(storageUtils.configFile(), this.prettyConfig(this.loadConfig(false))); - // } - - // handler(argv) { - // session.argv = argv; - // nconf.file('local', storageUtils.configFile()); - - // // show all - // if (argv.key.length === 0) - // return log.info(this.prettyConfig(this.loadConfig(argv.all))); - - - // const v = nconf.get(argv.key); - - // // delete - // if (argv.delete) { - // if (v === undefined) return log.fatal('Key not found: ' + argv.key); - // nconf.clear(argv.key); - // return this.saveConfig(); - // } - - // // show - // if (argv.value.length === 0) { - // if (v === undefined) return log.fatal('Key not found: ' + argv.key); - // return log.info(this.prettyConfig(v)); - // } - - // // set - // try { - // nconf.set(argv.key, JSON.parse(argv.value)); - // } catch (e) { - // nconf.set(argv.key, JSON.parse('"' + argv.value + '"')); - // } - // return this.saveConfig(); - // }; -} - - - - -export const configCommand: ConfigCommand = new ConfigCommand(); - diff --git a/src/childProcessCall/commands/list.ts b/src/childProcessCall/commands/list.ts deleted file mode 100644 index 4548b22..0000000 --- a/src/childProcessCall/commands/list.ts +++ /dev/null @@ -1,73 +0,0 @@ - -/* - * Filename: https://github.com/ccagml/vscode-leetcode-problem-rating/src/childProcessCall/commands/list.ts - * Path: https://github.com/ccagml/vscode-leetcode-problem-rating - * Created Date: Thursday, October 27th 2022, 7:43:29 pm - * Author: ccagml - * - * Copyright (c) 2022 ccagml . All rights reserved. - */ - - -import { helper } from "../helper"; -import { log } from "../log"; -import { corePlugin } from "../core"; -import { session } from "../session"; - -class ListCommand { - constructor() { - - } - - process_argv(argv) { - let argv_config = helper.base_argv().option('q', corePlugin.filters.query) - .option('s', { - alias: 'stat', - type: 'boolean', - default: false, - describe: 'Show statistics of listed questions' - }) - .option('t', corePlugin.filters.tag) - .option('x', { - alias: 'extra', - type: 'boolean', - default: false, - describe: 'Show extra details: category, companies, tags.' - }) - .option('T', { - alias: 'dontTranslate', - type: 'boolean', - default: false, - describe: 'Set to true to disable endpoint\'s translation', - }) - .positional('keyword', { - type: 'string', - default: '', - describe: 'Filter questions by keyword' - }); - - argv_config.process_argv(argv); - - return argv_config.get_result(); - } - - handler(argv) { - session.argv = argv; - corePlugin.filterProblems(argv, function (e, problems) { - if (e) return log.info(e); - let new_objcet: Array = []; - problems.forEach(element => { - let temp_ele: any = {}; - for (const key in element) { - if (key != "link") { - temp_ele[key] = element[key]; - } - } - new_objcet.push(temp_ele); - }); - log.info(JSON.stringify(new_objcet)); - }); - }; -} - -export const listCommand: ListCommand = new ListCommand(); diff --git a/src/childProcessCall/commands/plugin.ts b/src/childProcessCall/commands/plugin.ts deleted file mode 100644 index 7f187e4..0000000 --- a/src/childProcessCall/commands/plugin.ts +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Filename: https://github.com/ccagml/vscode-leetcode-problem-rating/src/childProcessCall/commands/plugin.ts - * Path: https://github.com/ccagml/vscode-leetcode-problem-rating - * Created Date: Thursday, October 27th 2022, 7:43:29 pm - * Author: ccagml - * - * Copyright (c) 2022 ccagml . All rights reserved. - */ - - -import { helper } from "../helper"; -import { config } from "../config"; -import { log } from "../log"; -import { myPluginBase } from "../my_plugin_base"; -import { session } from "../session"; - - -class PluginCommand { - constructor() { - - } - - process_argv = function (argv) { - let argv_config = helper.base_argv().option('d', { - alias: 'disable', - type: 'boolean', - describe: 'Disable plugin', - default: false - }).option('e', { - alias: 'enable', - type: 'boolean', - describe: 'Enable plugin', - default: false - }).option('i', { - alias: 'install', - type: 'boolean', - describe: 'Install plugin', - default: false - }).positional('name', { - type: 'string', - describe: 'Filter plugin by name', - default: '' - }); - - argv_config.process_argv(argv); - - return argv_config.get_result(); - }; - - handler = function (argv) { - session.argv = argv; - - let all_plugin = myPluginBase.installed; - const name = argv.name; - - // if (argv.install) { - // const cb = function (e, p) { - // if (e) return log.fatal(e); - // p.help(); - // p.save(); - // myPluginBase.init(); - // }; - - // return; - // } - - if (name) { - all_plugin = all_plugin.filter(x => x.name === name); - }; - if (all_plugin.length === 0) { - return log.fatal('Plugin not found!'); - } - - const p = all_plugin[0]; - if (argv.enable) { - p.enabled = true; - p.save(); - } else if (argv.disable) { - p.enabled = false; - p.save(); - } else if (argv.delete) { - // p.delete(); - p.save(); - myPluginBase.init(); - } else if (argv.config) { - log.info(JSON.stringify(config.plugins[name] || {}, null, 2)); - } - }; -} - - -export const pluginCommand: PluginCommand = new PluginCommand(); diff --git a/src/childProcessCall/commands/query.ts b/src/childProcessCall/commands/query.ts deleted file mode 100644 index 173e7e8..0000000 --- a/src/childProcessCall/commands/query.ts +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Filename: https://github.com/ccagml/vscode-leetcode-problem-rating/src/childProcessCall/commands/query.ts - * Path: https://github.com/ccagml/vscode-leetcode-problem-rating - * Created Date: Thursday, October 27th 2022, 7:43:29 pm - * Author: ccagml - * - * Copyright (c) 2022 ccagml . All rights reserved. - */ - - -import { helper } from "../helper"; -import { log } from "../log"; -import { corePlugin } from "../core"; -import { session } from "../session"; - -class QueryCommand { - constructor() { } - process_argv = function (argv) { - let argv_config = helper.base_argv().option('T', { - alias: 'dontTranslate', - type: 'boolean', - default: false, - describe: 'Set to true to disable endpoint\'s translation', - }).option('a', { - alias: 'getTodayQuestion', - type: 'boolean', - default: false, - describe: 'getTodayQuestion', - }).option('b', { - alias: 'username', - type: 'string', - default: "", - describe: 'user name', - }).option('c', { - alias: 'getRating', - type: 'boolean', - default: false, - describe: 'ranking', - }).option('z', { - alias: 'test', - type: 'string', - default: "", - describe: 'test', - }); - argv_config.process_argv(argv); - return argv_config.get_result(); - }; - - handler = function (argv) { - session.argv = argv; - if (argv.a) { - corePlugin.getTodayQuestion(function (e, result) { - if (e) return; - log.info(JSON.stringify(result)); - }); - } else if (argv.b) { - corePlugin.getUserContest(argv.b, function (e, result) { - if (e) return; - log.info(JSON.stringify(result)); - }); - } else if (argv.c) { - corePlugin.getRating(function (e, result) { - if (e) { - let log_data = { - code: 101, - data: {} - }; - log.info(JSON.stringify(log_data)); - return; - }; - let log_data = { - code: 100, - data: result - }; - log.info(JSON.stringify(log_data)); - }); - } - else if (argv.z) { - corePlugin.getQueryZ(argv.z, function (e, result) { - if (e) return; - log.info(JSON.stringify(result)); - }); - } - }; -} - - - -export const queryCommand: QueryCommand = new QueryCommand(); diff --git a/src/childProcessCall/commands/session.ts b/src/childProcessCall/commands/session.ts deleted file mode 100644 index e1955e6..0000000 --- a/src/childProcessCall/commands/session.ts +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Filename: https://github.com/ccagml/vscode-leetcode-problem-rating/src/childProcessCall/commands/session.ts - * Path: https://github.com/ccagml/vscode-leetcode-problem-rating - * Created Date: Thursday, October 27th 2022, 7:43:29 pm - * Author: ccagml - * - * Copyright (c) 2022 ccagml . All rights reserved. - */ - - - -// import { helper } from "../helper"; -// import { corePlugin } from "../core"; -// import { log } from "../log"; -// import { session } from "../session"; - - -class SessionCommand { - constructor() { - - } - - // printSessions(e, sessions) { - // if (e) return log.info(e); - - // log.info(' %6s %5s %18s %28s %16s', - // 'Active', 'Id', 'Name', 'AC Questions', 'AC Submits'); - // log.info('-'.repeat(80)); - - // for (let s of sessions) { - // let questionRate = 0; - // let submissionRate = 0; - // if (s.submitted_questions > 0) - // questionRate = s.ac_questions * 100 / s.submitted_questions; - // if (s.total_submitted > 0) - // submissionRate = s.total_acs * 100 / s.total_submitted; - - // log.info( - // s.is_active ? helper.prettyState('ac') : ' ', - // s.id, - // s.name || 'Anonymous Session', - // s.ac_questions, - // questionRate.toFixed(2), - // s.total_acs, - // submissionRate.toFixed(2)); - // } - // } - - // handler(argv) { - // session.argv = argv; - - // if (argv.create) - // return corePlugin.createSession(argv.keyword, this.printSessions); - - // let that = this; - // corePlugin.getSessions(function (e, sessions) { - // if (e) return log.info(e); - - // if (argv.keyword) { - // const id = Number(argv.keyword); - // sessions = sessions.filter(x => x.name === argv.keyword || x.id === id); - // if (sessions.length > 1) return log.info('Ambiguous sessions?'); - - // const session = sessions[0]; - // if (!session) return log.info('Session not found!'); - - // if (argv.enable && !session.is_active) { - // corePlugin.activateSession(session, function (e, sessions) { - // if (e) return log.info(e); - // require('../session').session.deleteCodingSession(); - // that.printSessions(e, sessions); - // }); - // return; - // } - - // if (argv.delete) { - // return corePlugin.deleteSession(session, that.printSessions); - // } - // } - // that.printSessions(null, sessions); - // }); - // }; -} - - -export const sessionCommand: SessionCommand = new SessionCommand(); diff --git a/src/childProcessCall/commands/show.ts b/src/childProcessCall/commands/show.ts deleted file mode 100644 index c09caf3..0000000 --- a/src/childProcessCall/commands/show.ts +++ /dev/null @@ -1,192 +0,0 @@ -/* - * Filename: https://github.com/ccagml/vscode-leetcode-problem-rating/src/childProcessCall/commands/show.ts - * Path: https://github.com/ccagml/vscode-leetcode-problem-rating - * Created Date: Thursday, October 27th 2022, 7:43:29 pm - * Author: ccagml - * - * Copyright (c) 2022 ccagml . All rights reserved. - */ - - -let util = require('util'); -let childProcess = require('child_process'); - - -import { helper } from "../helper"; -import { storageUtils } from "../storageUtils"; - -import { log } from "../log"; -import { config } from "../config"; -import { corePlugin } from "../core"; -import { session } from "../session"; - -class ShowCommand { - constructor() { - - } - - - process_argv = function (argv) { - let argv_config = helper.base_argv().option('c', { - alias: 'codeonly', - type: 'boolean', - default: false, - describe: 'Only show code template' - }).option('e', { - alias: 'editor', - type: 'string', - describe: 'Open source code in editor' - }).option('g', { - alias: 'gen', - type: 'boolean', - default: false, - describe: 'Generate source code' - }).option('l', { - alias: 'lang', - type: 'string', - default: config.code.lang, - describe: 'Programming language of the source code', - choices: config.sys.langs - }).option('o', { - alias: 'outdir', - type: 'string', - describe: 'Where to save source code', - default: '.' - }).option('q', corePlugin.filters.query) - .option('t', corePlugin.filters.tag) - .option('x', { - alias: 'extra', - type: 'boolean', - default: false, - describe: 'Show extra question details in source code' - }).option('T', { - alias: 'dontTranslate', - type: 'boolean', - default: false, - describe: 'Set to true to disable endpoint\'s translation', - }).positional('keyword', { - type: 'string', - default: '', - describe: 'Show question by name or id' - }); - argv_config.process_argv(argv); - return argv_config.get_result(); - }; - genFileName(problem, opts) { - const path = require('path'); - const params = [ - storageUtils.fmt(config.file.show, problem), - '', - helper.langToExt(opts.lang) - ]; - - // try new name to avoid overwrite by mistake - for (let i = 0; ; ++i) { - const name = path.join(opts.outdir, params.join('.').replace(/\.+/g, '.')); - if (!storageUtils.exist(name)) - return name; - params[1] = i; - } - } - - showProblem(problem, argv) { - const taglist = [problem.category] - .concat(problem.companies || []) - .concat(problem.tags || []) - .map(x => helper.badge(x)) - .join(' '); - const langlist = problem.templates - .map(x => helper.badge(x.value)) - .sort() - .join(' '); - - let code; - const needcode = argv.gen || argv.codeonly; - if (needcode) { - const template = problem.templates.find(x => x.value === argv.lang); - if (!template) { - log.info('Not supported language "' + argv.lang + '"'); - log.warn('Supported languages: ' + langlist); - return; - } - - const opts = { - lang: argv.lang, - code: template.defaultCode, - tpl: argv.extra ? 'detailed' : 'codeonly' - }; - code = corePlugin.exportProblem(problem, opts); - } - - let filename; - if (argv.gen) { - storageUtils.mkdir(argv.outdir); - filename = this.genFileName(problem, argv); - storageUtils.write(filename, code); - - if (argv.editor !== undefined) { - childProcess.spawn(argv.editor || config.code.editor, [filename], { - // in case your editor of choice is vim or emacs - stdio: 'inherit' - }); - } - } else { - if (argv.codeonly) { - log.info(code); - return; - } - } - - log.info(`[${problem.fid}] ${problem.name}`); - log.info(); - log.info(problem.link); - if (argv.extra) { - log.info(); - log.info('Tags: ' + taglist); - log.info(); - log.info('Langs: ' + langlist); - } - - log.info(); - log.info(`* ${problem.category}`); - log.info(`* ${helper.prettyLevel(problem.level)} (${problem.percent.toFixed(2)}%)`); - - if (problem.likes) - log.info(`* Likes: ${problem.likes}`); - if (problem.dislikes) - log.info(`* Dislikes: ${problem.dislikes}`); - else - log.info(`* Dislikes: -`); - if (problem.totalAC) - log.info(`* Total Accepted: ${problem.totalAC}`); - if (problem.totalSubmit) - log.info(`* Total Submissions: ${problem.totalSubmit}`); - if (problem.testable && problem.testcase) { - let testcase_value = util.inspect(problem.testcase); - log.info(`* Testcase Example: ${testcase_value}`); - } - if (filename) - log.info(`* Source Code: ${filename}`); - - log.info(); - log.info(problem.desc); - } - - handler(argv) { - let that = this; - session.argv = argv; - if (argv.keyword.length > 0) { - // show specific one - corePlugin.getProblem(argv.keyword, !argv.dontTranslate, function (e, problem) { - if (e) return log.info(e); - that.showProblem(problem, argv); - }); - } else { - // - } - }; -} - -export const showCommand: ShowCommand = new ShowCommand(); - - diff --git a/src/childProcessCall/commands/star.ts b/src/childProcessCall/commands/star.ts deleted file mode 100644 index 198cc45..0000000 --- a/src/childProcessCall/commands/star.ts +++ /dev/null @@ -1,58 +0,0 @@ - -/* - * Filename: https://github.com/ccagml/vscode-leetcode-problem-rating/src/childProcessCall/commands/star.ts - * Path: https://github.com/ccagml/vscode-leetcode-problem-rating - * Created Date: Thursday, October 27th 2022, 7:43:29 pm - * Author: ccagml - * - * Copyright (c) 2022 ccagml . All rights reserved. - */ - - -import { helper } from "../helper"; -import { log } from "../log"; -import { corePlugin } from "../core"; -import { session } from "../session"; - -class StarCommand { - constructor() { - - } - - process_argv(argv) { - let argv_config = helper.base_argv().option('d', { - alias: 'delete', - type: 'boolean', - describe: 'Unstar question', - default: false - }) - .positional('keyword', { - type: 'string', - describe: 'Question name or id', - default: '' - }); - - - argv_config.process_argv(argv); - - return argv_config.get_result(); - } - - handler(argv) { - session.argv = argv; - // translation doesn't affect question lookup - corePlugin.getProblem(argv.keyword, true, function (e, problem) { - if (e) return log.info(e); - - corePlugin.starProblem(problem, !argv.delete, function (e, starred) { - if (e) return log.info(e); - log.info(`[${problem.fid}] ${problem.name} ${starred ? 'icon.like' : 'icon.unlike'}`); - corePlugin.updateProblem(problem, { starred: starred }); - }); - }); - }; - -} - - -export const starCommand: StarCommand = new StarCommand(); diff --git a/src/childProcessCall/commands/stat.ts b/src/childProcessCall/commands/stat.ts deleted file mode 100644 index c207724..0000000 --- a/src/childProcessCall/commands/stat.ts +++ /dev/null @@ -1,220 +0,0 @@ -/* - * Filename: https://github.com/ccagml/vscode-leetcode-problem-rating/src/childProcessCall/commands/stat.ts - * Path: https://github.com/ccagml/vscode-leetcode-problem-rating - * Created Date: Thursday, October 27th 2022, 7:43:29 pm - * Author: ccagml - * - * Copyright (c) 2022 ccagml . All rights reserved. - */ - - -// let moment_out = require('moment'); -// let underscore = require('underscore'); - -// import { helper } from "../helper"; -// import { log } from "../log"; -// import { corePlugin } from "../core"; -// import { session } from "../session"; - -class StatCommand { - constructor() { - - } - - // process_argv(argv) { - // let argv_config = helper.base_argv().option('c', { - // alias: 'cal', - // type: 'boolean', - // default: false, - // describe: 'Show calendar statistics' - // }) - // .option('g', { - // alias: 'graph', - // type: 'boolean', - // default: false, - // describe: 'Show graphic statistics' - // }) - // .option('l', { - // alias: 'lock', - // type: 'boolean', - // default: true, - // describe: 'Include locked questions' - // }) - // .option('q', corePlugin.filters.query) - // .option('t', corePlugin.filters.tag); - // argv_config.process_argv(argv); - - // return argv_config.get_result(); - // } - - // printLine(key, done, all) { - // const n = 30; - // const percent = (all > 0) ? done / all : 0; - // const x = Math.ceil(n * percent); - // log.info(' %s\t%3s/%-3s (%6s %%) %s%s', - // helper.prettyLevel(key), done, all, - // (100 * percent).toFixed(2), - // '█'.repeat(x), - // '░'.repeat(n - x)); - // } - - // showProgress(problems) { - // const stats = { - // easy: { all: 0, ac: 0 }, - // medium: { all: 0, ac: 0 }, - // hard: { all: 0, ac: 0 } - // }; - - // for (let problem of problems) { - // const level = problem.level.toLowerCase(); - // const state = problem.state.toLowerCase(); - - // if (!(level in stats)) continue; - // ++stats[level].all; - - // if (!(state in stats[level])) continue; - // ++stats[level][state]; - // } - - // this.printLine('Easy', stats.easy.ac, stats.easy.all); - // this.printLine('Medium', stats.medium.ac, stats.medium.all); - // this.printLine('Hard', stats.hard.ac, stats.hard.all); - // } - - // showGraph(problems) { - // const ICONS = { - - // }; - - // let groups = 1; - - // const header = underscore.range(groups) - // .map(x => x * 10 + 1 + '' + x * 10 + 10) - // .join(''); - // log.info(' ' + header); - - // const graph: Array = []; - // for (let problem of problems) - // graph[problem.fid] = ICONS[problem.state] || ' ICONS.none '; - - // let line = ['0']; - // for (let i = 1, n = graph.length; i <= n; ++i) { - // // padding before group - // if (i % 10 === 1) line.push(' '); - - // line.push(graph[i] || ' ICONS.empty'); - - // // time to start new row - // if (i % (10 * groups) === 0 || i === n) { - // log.info(line.join(' ')); - // line = [' ' + i]; - // } - // } - - // log.info(); - // log.info('%7s%s%3s%s%3s%s', - // ' ', 'ICONS.ac' + ' Accepted', - // ' ', 'ICONS.notac' + ' Not Accepted', - // ' ', 'ICONS.none' + ' Remaining'); - // } - - // showCal(problems) { - // const MONTHS = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; - // const WEEKDAYS = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']; - // const ICONS = [ - // 'icon.none', - // 'icon.ac', - // 'icon.ac', - // 'icon.ac', - // 'icon.ac', - // ]; - - // const N_MONTHS = 12; - // const N_WEEKS = 53; - // const N_WEEKDAYS = 7; - - // const now = moment_out(); - - // const SCORES = { easy: 1, medium: 2, hard: 5 }; - // function toScore(sum, id) { - // const problem = problems.find(x => x.fid === id); - // if (problem) sum += (SCORES[problem.level.toLowerCase()] || 1); - // return sum; - // } - - // // load historical stats - // const graph: Array = []; - // const stats = require('../cache').get(helper.KEYS.stat) || {}; - // for (let k of underscore.keys(stats)) { - // const score = (stats[k]['ac.set'] || []).reduce(toScore, 0); - // if (score === 0) continue; - - // const d = moment_out(k, 'YYYY-MM-DD'); - // graph[now.diff(d, 'days')] = score; - // } - - // // print header - // const buf = Buffer.alloc(120, ' ', 'ascii'); - // for (let i = 0; i <= N_MONTHS; ++i) { - // // for day 1 in each month, calculate its column position in graph - // const d = now.clone().subtract(i, 'months').date(1); - // const idx = now.diff(d, 'days'); - - // const j = (N_WEEKS - idx / N_WEEKDAYS + 1) * 2; - // if (j >= 0) buf.write(MONTHS[d.month()], j); - // } - // log.info('%7s%s', ' ', buf.toString()); - - // // print graph - // for (let i = 0; i < N_WEEKDAYS; ++i) { - // const line: Array = []; - // // print day in week - // const idx = (now.day() + i + 1) % N_WEEKDAYS; - // line.push(WEEKDAYS[idx]); - - // for (let j = 0; j < N_WEEKS; ++j) { - // let idx = (N_WEEKS - j - 1) * N_WEEKDAYS + N_WEEKDAYS - i - 1; - // const d = now.clone().subtract(idx, 'days'); - - // // map count to icons index: - // // [0] => 0, [1,5] => 1, [6,10] => 2, [11,15] => 3, [16,) => 4 - // const count = graph[idx] || 0; - // idx = Math.floor((count - 1) / 5) + 1; - // if (idx > 4) idx = 4; - - // let icon = ICONS[idx]; - // // use different colors for adjacent months - // if (idx === 0 && d.month() % 2) icon = icon; - // line.push(icon); - // } - // log.info(line.join(' ')); - // } - - // log.info(); - // log.info('%8s%s%3s%s%3s%s%3s%s', - // ' ', ICONS[1] + ' 1~5', - // ' ', ICONS[2] + ' 6~10', - // ' ', ICONS[3] + ' 11~15', - // ' ', ICONS[4] + ' 16+'); - // } - - // handler(argv) { - // session.argv = argv; - // let that = this; - // corePlugin.filterProblems(argv, function (e, problems) { - // if (e) return log.info(e); - - // if (!argv.lock) - // problems = problems.filter(x => !x.locked); - - // log.info(); - // if (argv.graph) that.showGraph(problems); - // else if (argv.cal) that.showCal(problems); - // else that.showProgress(problems); - // log.info(); - // }); - // }; -} - -export const statCommand: StatCommand = new StatCommand(); - diff --git a/src/childProcessCall/commands/submit.ts b/src/childProcessCall/commands/submit.ts deleted file mode 100644 index 76cc91a..0000000 --- a/src/childProcessCall/commands/submit.ts +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Filename: https://github.com/ccagml/vscode-leetcode-problem-rating/src/childProcessCall/commands/submit.ts - * Path: https://github.com/ccagml/vscode-leetcode-problem-rating - * Created Date: Thursday, October 27th 2022, 7:43:29 pm - * Author: ccagml - * - * Copyright (c) 2022 ccagml . All rights reserved. - */ - - - -let util = require('util'); -let lodash = require('lodash'); - - -import { helper } from "../helper"; -import { storageUtils } from "../storageUtils"; -import { log } from "../log"; -import { corePlugin } from "../core"; -import { session } from "../session"; - - - -class SubmitCommand { - constructor() { - - } - - - process_argv(argv) { - let argv_config = helper.base_argv().positional('filename', { - type: 'string', - describe: 'Code file to submit', - default: '' - }); - argv_config.process_argv(argv); - - return argv_config.get_result(); - } - - - printResult(actual, k, log_obj) { - if (!actual.hasOwnProperty(k)) return; - - const v = actual[k] || ''; - const lines = Array.isArray(v) ? v : [v]; - for (let line of lines) { - if (k !== 'state') { - if (!log_obj.hasOwnProperty(lodash.startCase(k))) { - log_obj[lodash.startCase(k)] = [line]; - } else { - log_obj[lodash.startCase(k)].push(line); - } - } else { - log_obj.messages.push(line); - } - } - } - - printLine(log_obj, ...ret: any[]) { - const args = ret.slice(1); - const line = util.format.apply(util, args); - log_obj.messages.push(line); - } - - handler(argv) { - session.argv = argv; - if (!storageUtils.exist(argv.filename)) - return log.fatal('File ' + argv.filename + ' not exist!'); - - const meta = storageUtils.meta(argv.filename); - let that = this; - // translation doesn't affect problem lookup - corePlugin.getProblem(meta, true, function (e, problem) { - if (e) return log.info(e); - - problem.file = argv.filename; - problem.lang = meta.lang; - - corePlugin.submitProblem(problem, function (e, results) { - if (e) return log.info(e); - - const result = results[0]; - - let log_obj: any = {}; - log_obj.messages = []; - log_obj.system_message = {}; - log_obj.system_message.fid = problem.fid; - log_obj.system_message.id = problem.id; - log_obj.system_message.qid = problem.id; - log_obj.system_message.sub_type = "submit"; - log_obj.system_message.accepted = false; - - that.printResult(result, 'state', log_obj); - that.printLine(log_obj, result, '%d/%d cases passed (%s)', - result.passed, result.total, result.runtime); - - if (result.ok) { - session.updateStat('ac', 1); - session.updateStat('ac.set', problem.fid); - log_obj.system_message.accepted = true; - - (function () { - if (result.runtime_percentile) - that.printLine(log_obj, result, 'Your runtime beats %d %% of %s submissions', - result.runtime_percentile.toFixed(2), result.lang); - else - return log.warn('Failed to get runtime percentile.'); - if (result.memory && result.memory_percentile) - that.printLine(log_obj, result, 'Your memory usage beats %d %% of %s submissions (%s)', - result.memory_percentile.toFixed(2), result.lang, result.memory); - else - return log.warn('Failed to get memory percentile.'); - })(); - } else { - result.testcase = result.testcase.slice(1, -1).replace(/\\n/g, '\n'); - that.printResult(result, 'error', log_obj); - that.printResult(result, 'testcase', log_obj); - that.printResult(result, 'answer', log_obj); - that.printResult(result, 'expected_answer', log_obj); - that.printResult(result, 'stdout', log_obj); - } - log.info(JSON.stringify(log_obj)); - corePlugin.updateProblem(problem, { state: (result.ok ? 'ac' : 'notac') }); - }); - }); - }; -} - - -export const submitCommand: SubmitCommand = new SubmitCommand(); diff --git a/src/childProcessCall/commands/test.ts b/src/childProcessCall/commands/test.ts deleted file mode 100644 index 324c634..0000000 --- a/src/childProcessCall/commands/test.ts +++ /dev/null @@ -1,233 +0,0 @@ -/* - * Filename: https://github.com/ccagml/vscode-leetcode-problem-rating/src/childProcessCall/commands/test.ts - * Path: https://github.com/ccagml/vscode-leetcode-problem-rating - * Created Date: Thursday, October 27th 2022, 7:43:29 pm - * Author: ccagml - * - * Copyright (c) 2022 ccagml . All rights reserved. - */ - - - -let _ = require('underscore'); -let lodash = require('lodash'); - - -import { helper } from "../helper"; -import { storageUtils } from "../storageUtils"; -import { log } from "../log"; -import { corePlugin } from "../core"; -import { session } from "../session"; - - -class TestCommand { - constructor() { - - } - - - process_argv(argv) { - let argv_config = helper.base_argv().option('i', { - alias: 'interactive', - type: 'boolean', - default: false, - describe: 'Provide test case interactively' - }) - .option('t', { - alias: 'testcase', - type: 'string', - default: '', - describe: 'Provide test case' - }) - .option('a', { - alias: 'allcase', - type: 'boolean', - default: false, - describe: 'Provide all test case' - }) - .positional('filename', { - type: 'string', - default: '', - describe: 'Code file to test' - }); - - argv_config.process_argv(argv); - - return argv_config.get_result(); - } - - - printResult(actual, extra, k, log_obj) { - if (!actual.hasOwnProperty(k)) return; - // HACk: leetcode still return 'Accepted' even the answer is wrong!! - const v = actual[k] || ''; - if (k === 'state' && v === 'Accepted') return; - - // let ok = actual.ok; - - const lines = Array.isArray(v) ? v : [v]; - for (let line of lines) { - const extraInfo = extra ? ` (${extra})` : ''; - if (k !== 'state') { - let new_kk = lodash.startCase(k) + extraInfo; - if (!log_obj.hasOwnProperty(new_kk)) { - log_obj[new_kk] = [line]; - } else { - log_obj[new_kk].push(line); - } - } else { - log_obj.messages.push(line); - } - } - } - - runTest(argv) { - let that = this; - if (!storageUtils.exist(argv.filename)) - return log.fatal('File ' + argv.filename + ' not exist!'); - - const meta = storageUtils.meta(argv.filename); - - // [key: string]: string[]; - // messages: string[]; - - corePlugin.getProblem(meta, true, function (e, problem) { - if (e) return log.info(JSON.stringify({ messages: ["error"], code: [-1], error: [e.msg || e] })); - - if (!problem.testable) - return log.info(JSON.stringify({ messages: ["error"], code: [-2], error: ['not testable? please submit directly!'] })); - - if (argv.testcase) { - problem.testcase = argv.testcase.replace(/\\n/g, '\n'); - } - - if (argv.allcase) { - let new_desc = problem.desc; - new_desc = new_desc.replace(/<\/sup>/gm, '').replace(//gm, '^'); - new_desc = require('he').decode(require('cheerio').load(new_desc).root().text()); - // NOTE: wordwrap internally uses '\n' as EOL, so here we have to - // remove all '\r' in the raw string. - new_desc = new_desc.replace(/\r\n/g, '\n').replace(/^ /mg, '⁠'); - let input = (require('wordwrap')(120))(new_desc).split('\n'); - let temp_test: Array = []; - let start_flag = false; - let temp_collect = ""; - for (let all_input = 0; all_input < input.length; all_input++) { - const element = input[all_input]; - var check_index = element.indexOf("输入"); - if (check_index == -1) { - check_index = element.indexOf("Input:"); - } - if (check_index != -1) { - temp_collect += element.substring(check_index + 1); - start_flag = true; - continue; - } - - var check_index = element.indexOf("输出"); - if (check_index == -1) { - check_index = element.indexOf("Output:"); - } - if (check_index != -1) { - start_flag = false; - } - if (start_flag) { - temp_collect += element; - } else { - if (temp_collect.length > 0) { - let new_ele = temp_collect; - let temp_case: Array = []; - let wait_cur = ""; - let no_need_flag = false; - for (let index = new_ele.length - 1; index >= 0; index--) { - if (no_need_flag) { - if (new_ele[index] == ",") { - no_need_flag = false; - } - } else { - if (new_ele[index] == "=") { - temp_case.push(wait_cur.trim()); - no_need_flag = true; - wait_cur = ""; - } else { - wait_cur = new_ele[index] + wait_cur; - } - } - } - for (let index = temp_case.length - 1; index >= 0; index--) { - temp_test.push(temp_case[index]); - } - temp_collect = ""; - } - } - - } - - if (temp_test.length < 1) { - return; - } - let all_case = temp_test.join("\n"); - problem.testcase = all_case; - } - - if (!problem.testcase) - return log.info(JSON.stringify({ messages: ["error"], code: [-3], error: ['missing testcase?'] })); - - problem.file = argv.filename; - problem.lang = meta.lang; - - corePlugin.testProblem(problem, function (e, results) { - if (e) return log.info(JSON.stringify(e)); - - - results = _.sortBy(results, x => x.type); - - let log_obj: any = {}; - log_obj.messages = []; - log_obj.system_message = {}; - log_obj.system_message.fid = problem.fid; - log_obj.system_message.id = problem.id; - log_obj.system_message.qid = problem.id; - log_obj.system_message.sub_type = "test"; - log_obj.system_message.accepted = false; - - if (results[0].state === 'Accepted') { - results[0].state = 'Finished'; - log_obj.system_message.accepted = true; - } - that.printResult(results[0], null, 'state', log_obj); - that.printResult(results[0], null, 'error', log_obj); - - results[0].your_input = problem.testcase; - results[0].output = results[0].answer; - // LeetCode-CN returns the actual and expected answer into two separate responses - if (results[1]) { - results[0].expected_answer = results[1].answer; - } - results[0].stdout = results[0].stdout.slice(1, -1).replace(/\\n/g, '\n'); - that.printResult(results[0], null, 'your_input', log_obj); - that.printResult(results[0], results[0].runtime, 'output', log_obj); - that.printResult(results[0], null, 'expected_answer', log_obj); - that.printResult(results[0], null, 'stdout', log_obj); - log.info(JSON.stringify(log_obj)); - }); - }); - } - - handler(argv) { - let that = this; - session.argv = argv; - if (!argv.i) - return that.runTest(argv); - - helper.readStdin(function (e, data) { - if (e) return log.info(e); - - argv.testcase = data; - return that.runTest(argv); - }); - }; -} - - -export const testCommand: TestCommand = new TestCommand(); diff --git a/src/childProcessCall/commands/user.ts b/src/childProcessCall/commands/user.ts deleted file mode 100644 index 71a5739..0000000 --- a/src/childProcessCall/commands/user.ts +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Filename: https://github.com/ccagml/vscode-leetcode-problem-rating/src/childProcessCall/commands/user.ts - * Path: https://github.com/ccagml/vscode-leetcode-problem-rating - * Created Date: Thursday, October 27th 2022, 7:43:29 pm - * Author: ccagml - * - * Copyright (c) 2022 ccagml . All rights reserved. - */ - - -let prompt_out = require('prompt'); -import { helper } from "../helper"; -import { log } from "../log"; -import { corePlugin } from "../core"; -import { session } from "../session"; - -class UserCommand { - constructor() { - - } - - process_argv(argv) { - let argv_config = helper.base_argv().option('l', { - alias: 'login', - type: 'boolean', - default: false, - describe: 'Login' - }) - .option('c', { - alias: 'cookie', - type: 'boolean', - default: false, - describe: 'cookieLogin' - }) - .option('g', { - alias: 'github', - type: 'boolean', - default: false, - describe: 'githubLogin' - }) - .option('i', { - alias: 'linkedin', - type: 'boolean', - default: false, - describe: 'linkedinLogin' - }) - .option('L', { - alias: 'logout', - type: 'boolean', - default: false, - describe: 'Logout' - }); - - argv_config.process_argv(argv); - - return argv_config.get_result(); - } - - - handler(argv) { - session.argv = argv; - let user: any = null; - if (argv.login) { - // login - prompt_out.colors = false; - prompt_out.message = ''; - prompt_out.start(); - prompt_out.get([ - { name: 'login', required: true }, - { name: 'pass', required: true, hidden: true } - ], function (e, user) { - if (e) { - return log.info(JSON.stringify({ code: -1, msg: e.msg || e })); - } - - corePlugin.login(user, function (e, user) { - if (e) { - return log.info(JSON.stringify({ code: -2, msg: e.msg || e })); - } - log.info(JSON.stringify({ code: 100, user_name: user.name })); - }); - }); - } else if (argv.logout) { - // logout - user = corePlugin.logout(user, true); - if (user) - log.info(JSON.stringify({ code: 100, user_name: user.name })); - else - log.info(JSON.stringify({ code: -3, msg: 'You are not login yet?' })); - // third parties - } else if (argv.github || argv.linkedin) { - // add future third parties here - const functionMap = new Map( - [ - ['g', corePlugin.githubLogin], - ['github', corePlugin.githubLogin], - ['i', corePlugin.linkedinLogin], - ['linkedin', corePlugin.linkedinLogin], - ] - ); - const keyword = Object.entries(argv).filter((i) => (i[1] === true))[0][0]; - const coreFunction = functionMap.get(keyword); - if (coreFunction) { - prompt_out.colors = false; - prompt_out.message = ''; - prompt_out.start(); - prompt_out.get([ - { name: 'login', required: true }, - { name: 'pass', required: true, hidden: true } - ], function (e, user) { - if (e) return log.info(JSON.stringify({ code: -4, msg: e.msg || e })); - coreFunction(user, function (e, user) { - if (e) return log.info(JSON.stringify({ code: -5, msg: e.msg || e })); - log.info(JSON.stringify({ code: 100, user_name: user.name })); - }); - }); - } - - } else if (argv.cookie) { - // session - prompt_out.colors = false; - prompt_out.message = ''; - prompt_out.start(); - prompt_out.get([ - { name: 'login', required: true }, - { name: 'cookie', required: true } - ], function (e, user) { - if (e) return log.info(e); - corePlugin.cookieLogin(user, function (e, user) { - if (e) return log.info(JSON.stringify({ code: -6, msg: e.msg || e })); - log.info(JSON.stringify({ code: 100, user_name: user.name })); - }); - }); - } else { - // show current user - user = session.getUser(); - if (user) { - log.info(JSON.stringify({ code: 100, user_name: user.name })); - } else - return log.info(JSON.stringify({ code: -7, msg: 'You are not login yet?' })); - } - }; -} - - - -export const userCommand: UserCommand = new UserCommand(); diff --git a/src/childProcessCall/config.ts b/src/childProcessCall/config.ts deleted file mode 100644 index fcb4ebd..0000000 --- a/src/childProcessCall/config.ts +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Filename: https://github.com/ccagml/vscode-leetcode-problem-rating/src/childProcessCall/config.ts - * Path: https://github.com/ccagml/vscode-leetcode-problem-rating - * Created Date: Thursday, October 27th 2022, 7:43:29 pm - * Author: ccagml - * - * Copyright (c) 2022 ccagml . All rights reserved. - */ - - -let underscore = require('underscore'); - -class Config { - app; - sys; - autologin; - code; - file; - color; - icon; - network; - plugins; - constructor() { - this.sys = { - categories: [ - 'algorithms', - 'LCCI', - 'LCOF', - 'LCOF2' - ], - langs: [ - 'bash', - 'c', - 'cpp', - 'csharp', - 'golang', - 'java', - 'javascript', - 'kotlin', - 'mysql', - 'php', - 'python', - 'python3', - 'ruby', - 'rust', - 'scala', - 'swift', - 'typescript' - ], - urls: { - // base urls - base: 'https://leetcode.com', - graphql: 'https://leetcode.com/graphql', - login: 'https://leetcode.com/accounts/login/', - // third part login base urls. TODO facebook google - github_login: 'https://leetcode.com/accounts/github/login/?next=%2F', - facebook_login: 'https://leetcode.com/accounts/facebook/login/?next=%2F', - linkedin_login: 'https://leetcode.com/accounts/linkedin_oauth2/login/?next=%2F', - // redirect urls - leetcode_redirect: 'https://leetcode.com/', - github_tf_redirect: 'https://github.com/sessions/two-factor', - // simulate login urls - github_login_request: 'https://github.com/login', - github_session_request: 'https://github.com/session', - github_tf_session_request: 'https://github.com/sessions/two-factor', - linkedin_login_request: 'https://www.linkedin.com/login', - linkedin_session_request: 'https://www.linkedin.com/checkpoint/lg/login-submit', - // questions urls - problems: 'https://leetcode.com/api/problems/$category/', - problem: 'https://leetcode.com/problems/$slug/description/', - test: 'https://leetcode.com/problems/$slug/interpret_solution/', - session: 'https://leetcode.com/session/', - submit: 'https://leetcode.com/problems/$slug/submit/', - submissions: 'https://leetcode.com/api/submissions/$slug', - submission: 'https://leetcode.com/submissions/detail/$id/', - verify: 'https://leetcode.com/submissions/detail/$id/check/', - favorites: 'https://leetcode.com/list/api/questions', - favorite_delete: 'https://leetcode.com/list/api/questions/$hash/$id', - problem_detail: '', - noj_go: '', - u: '', - }, - }; - - this.autologin = { - enable: false, - retry: 2 - }; - this.code = { - editor: 'vim', - lang: 'cpp' - }; - this.file = { - show: '${fid}.${slug}', - submission: '${fid}.${slug}.${sid}.${ac}' - }; - this.color = { - enable: true, - theme: 'default' - }; - this.icon = { - theme: '' - }; - this.network = { - concurrency: 10, - delay: 1 - }; - this.plugins = {}; - } - - init() { - }; - - getAll(useronly) { - const cfg = underscore.extendOwn({}, this); - if (useronly) delete cfg.sys; - return cfg; - }; - - fix_cn() { - this.app = 'leetcode.cn'; - this.sys.urls.base = 'https://leetcode.cn'; - this.sys.urls.login = 'https://leetcode.cn/accounts/login/'; - this.sys.urls.problems = 'https://leetcode.cn/api/problems/$category/'; - this.sys.urls.problem = 'https://leetcode.cn/problems/$slug/description/'; - this.sys.urls.graphql = 'https://leetcode.cn/graphql'; - this.sys.urls.problem_detail = 'https://leetcode.cn/graphql'; - this.sys.urls.test = 'https://leetcode.cn/problems/$slug/interpret_solution/'; - this.sys.urls.session = 'https://leetcode.cn/session/'; - this.sys.urls.submit = 'https://leetcode.cn/problems/$slug/submit/'; - this.sys.urls.submissions = 'https://leetcode.cn/api/submissions/$slug'; - this.sys.urls.submission = 'https://leetcode.cn/submissions/detail/$id/'; - this.sys.urls.verify = 'https://leetcode.cn/submissions/detail/$id/check/'; - this.sys.urls.favorites = 'https://leetcode.cn/list/api/questions'; - this.sys.urls.favorite_delete = 'https://leetcode.cn/list/api/questions/$hash/$id'; - this.sys.urls.noj_go = 'https://leetcode.cn/graphql/noj-go/'; - this.sys.urls.u = 'https://leetcode.cn/u/$username/'; - this.sys.urls.github_login = 'https://leetcode.cn/accounts/github/login/?next=%2F'; - this.sys.urls.linkedin_login = 'https://leetcode.cn/accounts/linkedin_oauth2/login/?next=%2F'; - this.sys.urls.leetcode_redirect = 'https://leetcode.cn/'; - } -} - - -export const config: Config = new Config(); diff --git a/src/childProcessCall/helper.ts b/src/childProcessCall/helper.ts deleted file mode 100644 index e9c9c07..0000000 --- a/src/childProcessCall/helper.ts +++ /dev/null @@ -1,285 +0,0 @@ -/* - * Filename: https://github.com/ccagml/vscode-leetcode-problem-rating/src/childProcessCall/helper.ts - * Path: https://github.com/ccagml/vscode-leetcode-problem-rating - * Created Date: Thursday, October 27th 2022, 7:43:29 pm - * Author: ccagml - * - * Copyright (c) 2022 ccagml . All rights reserved. - */ - - -let ora = require('ora'); - -import { storageUtils } from "./storageUtils"; - -// export const UNITS_SIZE = [ -// { unit: 'B', name: 'Bytes', count: 1024 }, -// { unit: 'K', name: 'KBytes', count: 1024 }, -// { unit: 'M', name: 'MBytes', count: 1024 }, -// { unit: 'G', name: 'GBytes', count: -1 } -// ]; - -// export const UNITS_TIME = [ -// { unit: 's', name: 'seconds', count: 60 }, -// { unit: 'm', name: 'minutes', count: 60 }, -// { unit: 'h', name: 'hours', count: 24 }, -// { unit: 'd', name: 'days', count: 7 }, -// { unit: 'w', name: 'weeks', count: 4 }, -// { unit: 'm', name: 'months', count: 12 }, -// { unit: 'y', name: 'years', count: -1 } -// ]; - -// export function getUnit(units, v) { -// for (let i = 0; i < units.length; ++i) { -// if (units[i].count <= 0 || v < units[i].count) -// return [v, units[i]]; -// v /= units[i].count; -// } -// return []; -// } - -export const LANGS = [ - { lang: 'bash', ext: '.sh', style: '#' }, - { lang: 'c', ext: '.c', style: 'c' }, - { lang: 'cpp', ext: '.cpp', style: 'c' }, - { lang: 'csharp', ext: '.cs', style: 'c' }, - { lang: 'golang', ext: '.go', style: 'c' }, - { lang: 'java', ext: '.java', style: 'c' }, - { lang: 'javascript', ext: '.js', style: 'c' }, - { lang: 'kotlin', ext: '.kt', style: 'c' }, - { lang: 'mysql', ext: '.sql', style: '--' }, - { lang: 'php', ext: '.php', style: 'c' }, - { lang: 'python', ext: '.py', style: '#' }, - { lang: 'python3', ext: '.py', style: '#' }, - { lang: 'ruby', ext: '.rb', style: '#' }, - { lang: 'rust', ext: '.rs', style: 'c' }, - { lang: 'scala', ext: '.scala', style: 'c' }, - { lang: 'swift', ext: '.swift', style: 'c' }, - { lang: 'typescript', ext: '.ts', style: 'c' } -]; - -class HELPER { - KEYS; - constructor() { - this.KEYS = { - user: '../user', - stat: '../stat', - plugins: '../../plugins', - problems: 'problems', - translation: 'translationConfig', - ranting_path: '../../rating', - problem: p => p.fid + '.' + p.slug + '.' + p.category - }; - } - - // prettyState(state) { - // switch (state) { - // case 'ac': return this.prettyText('', true); - // case 'notac': return this.prettyText('', false); - // default: return ' '; - // } - // }; - - // prettyText(text, yesNo) { - // const icon = require('./icon'); - // switch (yesNo) { - // case true: return (icon.yes + text); - // case false: return (icon.no + text); - // default: return text; - // } - // }; - - // prettySize(n) { - // const res = getUnit(UNITS_SIZE, n) || []; - // return res[0].toFixed(2) + res[1].unit; - // }; - - // prettyTime(n) { - // const res = getUnit(UNITS_TIME, n) || []; - // return res[0].toFixed(0) + ' ' + res[1].name; - // }; - - prettyLevel(level) { - switch (level.toLowerCase().trim()) { - case 'easy': return (level); - case 'medium': return (level); - case 'hard': return (level); - default: return level; - } - }; - - levelToName(level) { - switch (level) { - case 1: return 'Easy'; - case 2: return 'Medium'; - case 3: return 'Hard'; - default: return ' '; - } - }; - - statusToName(sc) { - switch (sc) { - case 10: return 'Accepted'; - case 11: return 'Wrong Answer'; - case 12: return 'Memory Limit Exceeded'; - case 13: return 'Output Limit Exceeded'; - case 14: return 'Time Limit Exceeded'; - case 15: return 'Runtime Error'; - case 16: return 'Internal Error'; - case 20: return 'Compile Error'; - case 21: return 'Unknown Error'; - default: return 'Unknown'; - } - }; - - langToExt(lang) { - const res = LANGS.find(x => x.lang === lang); - return res ? res.ext : '.raw'; - }; - - extToLang(fullpath) { - const res = LANGS.find(x => fullpath.endsWith(x.ext)); - return res ? res.lang : 'unknown'; - }; - - langToCommentStyle(lang) { - const res = LANGS.find(x => x.lang === lang); - - return (res && res.style === 'c') ? - { start: '/*', line: ' *', end: ' */', singleLine: '//' } : - { start: res?.style, line: res?.style, end: res?.style, singleLine: res?.style }; - }; - - readStdin(cb) { - const stdin = process.stdin; - let bufs: Array = []; - - console.log('NOTE: to finish the input, press ' + - (storageUtils.isWindows() ? ' and ' : '')); - - stdin.on('readable', function () { - const data = stdin.read(); - if (data) { - // windows doesn't treat ctrl-D as EOF - if (storageUtils.isWindows() && data.toString() === '\x04\r\n') { - stdin.emit('end'); - } else { - bufs.push(data); - } - } - }); - stdin.on('end', function () { - cb(null, Buffer.concat(bufs).toString()); - }); - stdin.on('error', cb); - }; - - getSetCookieValue(resp, key) { - const cookies = resp.headers['set-cookie']; - if (!cookies) return null; - - for (let i = 0; i < cookies.length; ++i) { - const sections = cookies[i].split(';'); - for (let j = 0; j < sections.length; ++j) { - const kv = sections[j].trim().split('='); - if (kv[0] === key) return kv[1]; - } - } - return null; - }; - - printSafeHTTP(msg) { - return msg.replace(/(Cookie\s*:\s*)'.*?'/, '$1') - .replace(/('X-CSRFToken'\s*:\s*)'.*?'/, '$1') - .replace(/('set-cookie'\s*:\s*)\[.*?\]/, '$1'); - }; - - spin(s) { - return ora(s).start(); - }; - - badge(s) { - s = ' ' + s + ' '; - return (s); - }; - - base_argv() { - let base = { - all_base_data: {}, - positional_index: 0, - positional_key: {}, - option: function (key, value) { - this.all_base_data[key] = value.default; - this.all_base_data[value.alias] = value.default; - this[key] = value; - return this; - }, - positional: function (key, value) { - this.positional_key[this.positional_index] = key; - this.positional_index = this.positional_index + 1; - this.all_base_data[key] = value.default; - this.all_base_data[value.alias] = value.default; - this[key] = value; - return this; - }, - set_opt(key, temp_val?) { - let cfg = this[key]; - if (cfg) { - if (cfg.type == "boolean") { - this.all_base_data[key] = true; - if (cfg.alias) { - this.all_base_data[cfg.alias] = true; - } - return false; - } else { - this.all_base_data[key] = temp_val; - if (cfg.alias) { - this.all_base_data[cfg.alias] = temp_val; - } - return true; - } - } else { - this.all_base_data[key] = true; - } - return false; - }, - set_posi(value, index) { - let cfg_key = this.positional_key[index]; - let cfg = this[cfg_key]; - if (cfg) { - this.all_base_data[cfg_key] = value; - if (cfg.alias) { - this.all_base_data[cfg.alias] = value; - } - } - }, - process_argv(argv) { - let all_posi = 0; - for (let index = 3; index < argv.length; index++) { - let con = argv[index]; - if (con[0] == '-' && con[1] == '-') { - this.set_opt(con.substring(2)); - } - else if (con[0] == '-') { - for (let con_index = 1; con_index < con.length; con_index++) { - if (this.set_opt(con[con_index], argv[index + 1])) { - con_index++; - } - } - } else { - this.set_posi(con, all_posi); - all_posi = all_posi + 1; - } - } - }, - get_result: function () { - return this.all_base_data; - } - }; - return base; - } -} - - - -export const helper: HELPER = new HELPER(); diff --git a/src/childProcessCall/log.ts b/src/childProcessCall/log.ts deleted file mode 100644 index 37bea8d..0000000 --- a/src/childProcessCall/log.ts +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Filename: https://github.com/ccagml/vscode-leetcode-problem-rating/src/childProcessCall/log.ts - * Path: https://github.com/ccagml/vscode-leetcode-problem-rating - * Created Date: Thursday, October 27th 2022, 7:43:29 pm - * Author: ccagml - * - * Copyright (c) 2022 ccagml . All rights reserved. - */ - - -let _ = require('underscore'); - - -class LOG { - output = _.bind(console.log, console); - level; - levels = new Map([ - ['INFO', { value: 2 }], - ['WARN', { value: 3 }], - ['ERROR', { value: 4 }], - ]); - setLevel(name) { - this.level = this.levels.get(name) || this.levels.get('INFO'); - }; - - fail(e) { - let msg = (e.msg || e); - if (e.statusCode) { - msg += (' [code=' + e.statusCode + ']'); - } - this.error(msg); - }; - - fatal(e) { - this.error(e); - process.exit(1); - }; - - init() { - this.setLevel('INFO'); - }; - - info(...rest: any[]) { - const args = rest; //Array.from(arguments); - let s = args.map(x => x.toString()).join(' '); - this.output(s); - }; - warn(...rest: any[]) { - const args = rest; //Array.from(arguments); - args.unshift('[' + "warn" + ']'); - - let s = args.map(x => x.toString()).join(' '); - this.output(s); - }; - error(...rest: any[]) { - const args = rest; //Array.from(arguments); - args.unshift('[' + "error" + ']'); - - let s = args.map(x => x.toString()).join(' '); - this.output(s); - }; -} - -export const log: LOG = new LOG(); diff --git a/src/childProcessCall/my_plugin_base.ts b/src/childProcessCall/my_plugin_base.ts deleted file mode 100644 index 7e97349..0000000 --- a/src/childProcessCall/my_plugin_base.ts +++ /dev/null @@ -1,200 +0,0 @@ -/* - * Filename: https://github.com/ccagml/vscode-leetcode-problem-rating/src/childProcessCall/my_plugin_base.ts - * Path: https://github.com/ccagml/vscode-leetcode-problem-rating - * Created Date: Thursday, October 27th 2022, 7:43:29 pm - * Author: ccagml - * - * Copyright (c) 2022 ccagml . All rights reserved. - */ - - -let underscore = require('underscore'); - -import { config as out_config } from "./config"; -import { storageUtils } from "./storageUtils"; -// import { log } from "./log"; -import { helper } from "./helper"; - -export class MyPluginBase { - id; - name; - ver; - desc; - enabled; - deleted; - builtin; - deps; - next; - plugins: Array = []; - installed: Array = []; - head; // 插件头 是core - config; - constructor() { - } - - public save() { - const stats = storageUtils.getCache(helper.KEYS.plugins) || {}; - - if (this.deleted) delete stats[this.name]; - else stats[this.name] = this.enabled; - - storageUtils.setCache(helper.KEYS.plugins, stats); - }; - - public init() { - this.config = out_config.plugins[this.name] || {}; - this.next = null; - }; - - public base_init(head?) { - head = head || require('./core').corePlugin; - const stats = storageUtils.getCache(helper.KEYS.plugins) || {}; - let file_plugin: Array = storageUtils.listCodeDir('plugins'); - this.installed = []; - for (let f of file_plugin) { - const p = f.data; - if (!p) continue; - p.file = f.file; - p.enabled = stats[p.name]; - if (!(p.name in stats)) { - if (p.builtin) { - p.enabled = true; - } else { - p.enabled = false; - } - } - this.installed.push(p); - } - // 根据id大小排序, 大的前面 - this.installed = underscore.sortBy(this.installed, x => -x.id); - // 从小的开始init - for (let i = this.installed.length - 1; i >= 0; --i) { - const p = this.installed[i]; - if (p.enabled) { - p.init(); - } - } - // 连成链表状 - this.plugins = this.installed.filter(x => x.enabled); - let last = head; - for (let p of this.plugins) { - last.setNext(p); - last = p; - } - return true; - }; - - public setNext(next) { - Object.setPrototypeOf(this, next); - this.next = next; - }; - public save_all() { - for (let p of this.plugins) { - p.save(); - } - }; - - public getProblems(Translate: boolean, cb) { - this.next.getProblems(Translate, cb); - } - public getQuestionOfToday(cb) { - this.next.getQuestionOfToday(cb); - } - - public getRatingOnline(cb) { - this.next.getRatingOnline(cb); - } - - public getTestApi(username, cb) { - this.next.getTestApi(username, cb); - } - public getUserContestP(username, cb) { - this.next.getUserContestP(username, cb); - } - public getProblemsTitle(cb) { - this.next.getProblemsTitle(cb); - } - public createSession(a, cb) { - this.next.createSession(a, cb); - } - public getSessions(cb) { - this.next.getSessions(cb); - } - public activateSession(s, cb) { - this.next.activateSession(s, cb); - - } - public deleteSession(s, cb) { - this.next.deleteSession(s, cb); - - } - public updateProblem(a, b) { - this.next.updateProblem(a, b); - - } - public getSubmissions(s, cb) { - this.next.getSubmissions(s, cb); - - } - public getSubmission(s, cb) { - this.next.getSubmission(s, cb); - - } - public submitProblem(s, cb) { - this.next.submitProblem(s, cb); - - } - public testProblem(s, cb) { - this.next.testProblem(s, cb); - - } - public login(user, cb) { - this.next.login(user, cb); - - } - public logout(user, cb) { - this.next.logout(user, cb); - - } - public githubLogin(user, cb) { - this.next.githubLogin(user, cb); - - } - public linkedinLogin(user, cb) { - this.next.linkedinLogin(user, cb); - - } - public cookieLogin(user, cb) { - this.next.cookieLogin(user, cb); - } - public filterProblems(opts, cb) { - this.next.filterProblems(opts, cb); - } - - public getProblem(keyword, needTranslation, cb) { - this.next.getProblem(keyword, needTranslation, cb); - } - - public starProblem(problem, starred, cb) { - this.next.starProblem(problem, starred, cb); - } - public exportProblem(problem, opts) { - this.next.exportProblem(problem, opts); - } - - public getTodayQuestion(cb) { - this.next.getTodayQuestion(cb); - } - - public getQueryZ(username, cb) { - this.next.getQueryZ(username, cb); - } - - public getUserContest(username, cb) { - this.next.getUserContest(username, cb); - } -} - - - -export const myPluginBase: MyPluginBase = new MyPluginBase(); diff --git a/src/childProcessCall/plugins/cache.ts b/src/childProcessCall/plugins/cache.ts deleted file mode 100644 index e94fbf9..0000000 --- a/src/childProcessCall/plugins/cache.ts +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Filename: https://github.com/ccagml/vscode-leetcode-problem-rating/src/childProcessCall/plugins/cache.ts - * Path: https://github.com/ccagml/vscode-leetcode-problem-rating - * Created Date: Thursday, October 27th 2022, 7:43:29 pm - * Author: ccagml - * - * Copyright (c) 2022 ccagml . All rights reserved. - */ - - -import { MyPluginBase } from "../my_plugin_base"; - -let underscore = require('underscore'); - - -import { storageUtils } from "../storageUtils"; -import { helper } from "../helper"; -// import { log } from "../log"; -import { session } from "../session"; - - - -class CachePlugin extends MyPluginBase { - id = 50; - name = 'cache'; - builtin = true; - constructor() { - super(); - } - - clearCacheIfTchanged = (needTranslation) => { - const translationConfig = storageUtils.getCache(helper.KEYS.translation); - if (!translationConfig || translationConfig['useEndpointTranslation'] != needTranslation) { - storageUtils.deleteAllCache(); - storageUtils.setCache(helper.KEYS.translation, { useEndpointTranslation: needTranslation }); - } - }; - - public getProblems = (needTranslation, cb) => { - this.clearCacheIfTchanged(needTranslation); - const problems = storageUtils.getCache(helper.KEYS.problems); - if (problems) { - return cb(null, problems); - } - this.next.getProblems(needTranslation, function (e, problems) { - if (e) return cb(e); - storageUtils.setCache(helper.KEYS.problems, problems); - return cb(null, problems); - }); - }; - - /** - * getRatingOnline - */ - public getRatingOnline = (cb) => { - const cacheRantingData = storageUtils.getCache(helper.KEYS.ranting_path); - if (cacheRantingData) { - return cb(null, cacheRantingData); - } - this.next.getRatingOnline(function (e, ratingData) { - if (e) return cb(e); - let ratingObj; - try { - ratingObj = JSON.parse(ratingData); - } catch (error) { - return cb("JSON.parse(ratingData) error"); - } - storageUtils.setCache(helper.KEYS.ranting_path, ratingObj); - return cb(null, ratingObj); - }); - }; - - - public getProblem = (problem, needTranslation, cb) => { - this.clearCacheIfTchanged(needTranslation); - const k = helper.KEYS.problem(problem); - const _problem = storageUtils.getCache(k); - let that = this; - if (_problem) { - if (!_problem.desc.includes('
')) {
-                //
-            } else if (!['likes', 'dislikes'].every(p => p in _problem)) {
-                //
-            } else {
-
-                underscore.extendOwn(problem, _problem);
-                return cb(null, problem);
-            }
-        }
-        this.next.getProblem(problem, needTranslation, function (e, _problem) {
-            if (e) return cb(e);
-
-            that.saveProblem(_problem);
-            return cb(null, _problem);
-        });
-    };
-
-    saveProblem = (problem) => {
-        const _problem = underscore.omit(problem, ['locked', 'state', 'starred']);
-        return storageUtils.setCache(helper.KEYS.problem(problem), _problem);
-    };
-
-    updateProblem = (problem, kv) => {
-        const problems = storageUtils.getCache(helper.KEYS.problems);
-        if (!problems) return false;
-
-        const _problem = problems.find(x => x.id === problem.id);
-        if (!_problem) return false;
-
-        underscore.extend(_problem, kv);
-        return storageUtils.setCache(helper.KEYS.problems, problems);
-    };
-
-    login = (user, cb) => {
-        this.logout(user, false);
-        this.next.login(user, function (e, user) {
-            if (e) return cb(e);
-            session.saveUser(user);
-            return cb(null, user);
-        });
-    };
-
-    logout = (user, purge) => {
-        if (!user) user = session.getUser();
-        if (purge) session.deleteUser();
-        // NOTE: need invalidate any user related cache
-        session.deleteCodingSession();
-        return user;
-    };
-}
-
-
-export const pluginObj: CachePlugin = new CachePlugin();
diff --git a/src/childProcessCall/plugins/solution.discuss.ts b/src/childProcessCall/plugins/solution.discuss.ts
deleted file mode 100644
index ac24a4f..0000000
--- a/src/childProcessCall/plugins/solution.discuss.ts
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Filename: https://github.com/ccagml/vscode-leetcode-problem-rating/src/childProcessCall/plugins/solution.discuss.ts
- * Path: https://github.com/ccagml/vscode-leetcode-problem-rating
- * Created Date: Thursday, October 27th 2022, 7:43:29 pm
- * Author: ccagml
- *
- * Copyright (c) 2022 ccagml . All rights reserved.
- */
-
-
-let request = require('request');
-
-
-import { log } from "../log";
-import { session } from "../session";
-import { MyPluginBase } from "../my_plugin_base";
-
-
-
-class SolutionDiscuss extends MyPluginBase {
-  id = 200;
-  name = "solution.discuss";
-  builtin = true;
-  constructor() {
-    super();
-  }
-
-
-  getProblem = (problem, needTranslation, cb) => {
-
-    this.next.getProblem(problem, needTranslation, function (e, problem) {
-      if (e || !session.argv.solution) return cb(e, problem);
-
-      let lang = session.argv.lang;
-      getSolution(problem, lang, function (e, solution) {
-        if (e) return cb(e);
-        if (!solution) return log.error('Solution not found for ' + lang);
-
-        let link = URL_DISCUSS.replace('$slug', problem.slug).replace('$id', solution.id);
-        let content = solution.post.content.replace(/\\n/g, '\n').replace(/\\t/g, '\t');
-
-        log.info();
-        log.info(problem.name);
-        log.info();
-        log.info(solution.title);
-        log.info();
-        log.info(link);
-        log.info();
-        log.info('* Lang:    ' + lang);
-        log.info('* Author:  ' + solution.post.author.username);
-        log.info('* Votes:   ' + solution.post.voteCount);
-        log.info();
-        log.info(content);
-      });
-    });
-  };
-
-}
-
-let URL_DISCUSSES = 'https://leetcode.com/graphql';
-let URL_DISCUSS = 'https://leetcode.com/problems/$slug/discuss/$id';
-
-function getSolution(problem, lang, cb) {
-  if (!problem) return cb();
-
-  if (lang === 'python3') lang = 'python';
-
-  let opts = {
-    url: URL_DISCUSSES,
-    json: true,
-    body: {
-      query: [
-        'query questionTopicsList($questionId: String!, $orderBy: TopicSortingOption, $skip: Int, $query: String, $first: Int!, $tags: [String!]) {',
-        '  questionTopicsList(questionId: $questionId, orderBy: $orderBy, skip: $skip, query: $query, first: $first, tags: $tags) {',
-        '    ...TopicsList',
-        '  }',
-        '}',
-        'fragment TopicsList on TopicConnection {',
-        '  totalNum',
-        '  edges {',
-        '    node {',
-        '      id',
-        '      title',
-        '      post {',
-        '        content',
-        '        voteCount',
-        '        author {',
-        '          username',
-        '        }',
-        '      }',
-        '    }',
-        '  }',
-        '}'
-      ].join('\n'),
-
-      operationName: 'questionTopicsList',
-      variables: JSON.stringify({
-        query: '',
-        first: 1,
-        skip: 0,
-        orderBy: 'most_votes',
-        questionId: '' + problem.id,
-        tags: [lang]
-      })
-    }
-  };
-  request(opts, function (e, resp, body) {
-    if (e) return cb(e);
-    if (resp.statusCode !== 200)
-      return cb({ msg: 'http error', statusCode: resp.statusCode });
-
-    const solutions = body.data.questionTopicsList.edges;
-    const solution = solutions.length > 0 ? solutions[0].node : null;
-    return cb(null, solution);
-  });
-}
-
-export const pluginObj: SolutionDiscuss = new SolutionDiscuss();
diff --git a/src/childProcessCall/storageUtils.ts b/src/childProcessCall/storageUtils.ts
deleted file mode 100644
index aae8e5e..0000000
--- a/src/childProcessCall/storageUtils.ts
+++ /dev/null
@@ -1,242 +0,0 @@
-/*
- * Filename: https://github.com/ccagml/vscode-leetcode-problem-rating/src/childProcessCall/storageUtils.ts
- * Path: https://github.com/ccagml/vscode-leetcode-problem-rating
- * Created Date: Thursday, October 27th 2022, 7:43:29 pm
- * Author: ccagml
- *
- * Copyright (c) 2022 ccagml . All rights reserved.
- */
-
-
-let fs = require('fs');
-let os = require('os');
-let path = require('path');
-
-let _ = require('underscore');
-let mkdirp = require('mkdirp');
-
-export interface IMETA {
-  id: string
-  fid: string
-  lang: string
-}
-
-//Object.assign({}, defaultMETA, {})
-export const defaultMETA: IMETA = {
-  id: "",
-  fid: "",
-  lang: "",
-};
-
-class StorageUtils {
-  public init() {
-    _.templateSettings = {
-      evaluate: /\{\{(.+?)\}\}/g,
-      interpolate: /\$\{(.+?)\}/g
-    };
-    this.mkdir(this.homeDir());
-  };
-
-  public isWindows() {
-    return process.platform === 'win32';
-  };
-
-  public userHomeDir() {
-    return process.env.HOME || process.env.USERPROFILE;
-  };
-
-  public homeDir() {
-    return path.join(this.userHomeDir(), '.lcpr');
-  };
-
-  public appDir() {
-    const config = require('./config');
-    return path.join(this.homeDir(), config.app || 'leetcode');
-  };
-
-  // 缓存目录
-  public cacheDir() {
-    return path.join(this.appDir(), 'cache');
-  };
-
-  // 代码目录
-  public codeDir(dir) {
-    return path.join(__dirname, dir || '');
-  };
-
-  // 缓存目录文件
-  public cacheFile(k) {
-    return path.join(this.cacheDir(), k + '.json');
-  };
-
-  // public configFile() {
-  //   return path.join(this.homeDir(), 'config.json');
-  // };
-
-  // 插件代码目录
-  public listCodeDir(dir) {
-    dir = this.codeDir(dir);
-    let that = this;
-    return this.list(dir).map(function (f) {
-      const fullpath = path.join(dir, f);
-      const ext = path.extname(f);
-      const name = path.basename(f, ext);
-
-      let data = null;
-      switch (ext) {
-        case '.js': data = require(fullpath).pluginObj; break;
-        case '.json': data = JSON.parse(that.getData(fullpath)); break;
-      }
-      return { name: name, data: data, file: f };
-    });
-  };
-
-
-  public initCache() {
-    this.mkdir(this.cacheDir());
-  };
-  public deleteAllCache() {
-    this.listCache().forEach(value => {
-      this.delCache(value.name);
-    });
-  };
-
-  public getCache(k) {
-    const fullpath = this.cacheFile(k);
-    if (!this.exist(fullpath)) return null;
-
-    return JSON.parse(this.getData(fullpath));
-  };
-
-  public setCache(k, v) {
-    const fullpath = this.cacheFile(k);
-    this.write(fullpath, JSON.stringify(v));
-    return true;
-  };
-
-  public delCache(k) {
-    const fullpath = this.cacheFile(k);
-    if (!this.exist(fullpath)) return false;
-
-    this.rm(fullpath);
-    return true;
-  };
-
-  public listCache(): Array {
-    let that = this;
-    return this.list(this.cacheDir())
-      .filter(x => path.extname(x) === '.json')
-      .map(function (filename) {
-        const k = path.basename(filename, '.json');
-        const stat = that.stat(that.cacheFile(k));
-        return {
-          name: k,
-          size: stat.size,
-          mtime: stat.mtime
-        };
-      });
-  };
-
-  public mkdir(fullpath) {
-    if (fs.existsSync(fullpath)) return;
-    mkdirp.sync(fullpath);
-  };
-
-  public exist(fullpath) {
-    return fs.existsSync(fullpath);
-  };
-
-  public rm(fullpath) {
-    return fs.unlinkSync(fullpath);
-  };
-
-  public mv(src, dst) {
-    return fs.renameSync(src, dst);
-  };
-
-  public list(dir) {
-    return fs.readdirSync(dir);
-  };
-
-  public stat(fullpath) {
-    return fs.statSync(fullpath);
-  };
-
-  public write(fullpath, data) {
-    return fs.writeFileSync(fullpath, data);
-  };
-
-  public name(fullpath) {
-    return path.basename(fullpath, path.extname(fullpath));
-  };
-
-  public getData(fullpath) {
-    return fs.existsSync(fullpath) ? fs.readFileSync(fullpath).toString() : null;
-  };
-
-  // 获取要提交测试的数据
-  public codeData(fullpath) {
-    const data = this.getData(fullpath);
-
-    if (data === null) {
-      return null;
-    }
-
-    const lines = data.split(/\r\n|\n|\r/);
-    const start = lines.findIndex(x => x.indexOf('@lc code=start') !== -1);
-    const end = lines.findIndex(x => x.indexOf('@lc code=end') !== -1);
-
-    if (start !== -1 && end !== -1 && start + 1 <= end) {
-      return lines.slice(start + 1, end).join(os.EOL);
-    }
-
-    return data;
-  };
-
-  // 加载输出模板数据
-  public render(tpl, data) {
-    const tplfile = path.join(__dirname, "..", "..", "..", "resources", "templates", tpl + '.tpl');
-    let result = _.template(this.getData(tplfile).replace(/\r\n/g, '\n'))(data);
-    if (this.isWindows()) {
-      result = result.replace(/\n/g, '\r\n');
-    } else {
-      result = result.replace(/\r\n/g, '\n');
-    }
-    return result;
-  };
-
-  public fmt(format, data) {
-    return _.template(format)(data);
-  };
-
-  // public metaByName(filename) {
-  //   const m = Object.assign({}, defaultMETA, {});
-
-  //   m.id = storageUtils.name(filename).split('.')[0];
-
-
-  //   if (filename.endsWith('.py3') || filename.endsWith('.python3.py'))
-  //     m.lang = 'python3';
-  //   else
-  //     m.lang = require('./helper').extToLang(filename);
-
-  //   return m;
-  // };
-
-  public meta(filename) {
-    const m = Object.assign({}, defaultMETA, {});
-    const line = this.getData(filename).split('\n').find(x => x.indexOf(' @lc app=') >= 0) || '';
-    // @lc app=leetcode.cn id=剑指 Offer II 116 lang=cpp
-    let id_right = line.split('id=')[1];
-    let lang_cat = id_right.split('lang=');
-    let id = lang_cat[0].trim();
-    let lang = lang_cat[1].trim();
-    m.id = id;
-    m.fid = id;
-    m.lang = lang;
-    return m;
-  };
-
-}
-
-export const storageUtils: StorageUtils = new StorageUtils();
diff --git a/src/controller/EventController.ts b/src/controller/EventController.ts
index 4f55adf..9cbb350 100644
--- a/src/controller/EventController.ts
+++ b/src/controller/EventController.ts
@@ -10,12 +10,12 @@
 import { eventService } from "../service/EventService";
 // 事件的控制器
 class EventContorller {
-    /**
-     * 监听事件
-     */
-    public add_event() {
-        eventService.add_event();
-    }
+  /**
+   * 监听事件
+   */
+  public add_event() {
+    eventService.add_event();
+  }
 }
 
 export const eventController: EventContorller = new EventContorller();
diff --git a/src/controller/FileButtonController.ts b/src/controller/FileButtonController.ts
index c3f5cf0..a40764b 100644
--- a/src/controller/FileButtonController.ts
+++ b/src/controller/FileButtonController.ts
@@ -7,31 +7,29 @@
  * Copyright (c) 2022 ccagml . All rights reserved.
  */
 
-
 import { ConfigurationChangeEvent, Disposable, languages, workspace } from "vscode";
 import { fileButtonService } from "../service/FileButtonService";
 // 文件按钮的控制器
 class FileButtonController implements Disposable {
+  private registeredProvider: Disposable | undefined;
+  private configurationChangeListener: Disposable;
 
-    private registeredProvider: Disposable | undefined;
-    private configurationChangeListener: Disposable;
-
-    constructor() {
-        this.configurationChangeListener = workspace.onDidChangeConfiguration((event: ConfigurationChangeEvent) => {
-            if (event.affectsConfiguration("leetcode-problem-rating.editor.shortcuts")) {
-                fileButtonService.refresh();
-            }
-        }, this);
+  constructor() {
+    this.configurationChangeListener = workspace.onDidChangeConfiguration((event: ConfigurationChangeEvent) => {
+      if (event.affectsConfiguration("leetcode-problem-rating.editor.shortcuts")) {
+        fileButtonService.refresh();
+      }
+    }, this);
 
-        this.registeredProvider = languages.registerCodeLensProvider({ scheme: "file" }, fileButtonService);
-    }
+    this.registeredProvider = languages.registerCodeLensProvider({ scheme: "file" }, fileButtonService);
+  }
 
-    public dispose(): void {
-        if (this.registeredProvider) {
-            this.registeredProvider.dispose();
-        }
-        this.configurationChangeListener.dispose();
+  public dispose(): void {
+    if (this.registeredProvider) {
+      this.registeredProvider.dispose();
     }
+    this.configurationChangeListener.dispose();
+  }
 }
 
 export const fileButtonController: FileButtonController = new FileButtonController();
diff --git a/src/controller/LoginController.ts b/src/controller/LoginController.ts
index 2d50c0c..09b5184 100644
--- a/src/controller/LoginController.ts
+++ b/src/controller/LoginController.ts
@@ -19,172 +19,174 @@ import { statusBarService } from "../service/StatusBarService";
 import { treeDataService } from "../service/TreeDataService";
 import { getLeetCodeEndpoint } from "../utils/ConfigUtils";
 
-
 // 登录控制器
 class LoginContorller {
-    constructor() { }
-
-    // 登录操作
-    public async signIn(): Promise {
-        const picks: Array> = [];
-        let qpOpiton: QuickPickOptions = {
-            title: "正在登录leetcode.com",
-            matchOnDescription: false,
-            matchOnDetail: false,
-            placeHolder: "请选择登录方式 正在登录leetcode.com",
-        };
-        if (getLeetCodeEndpoint() == Endpoint.LeetCodeCN) {
-            picks.push({
-                label: "LeetCode Account",
-                detail: "只能登录leetcode.cn",
-                value: "LeetCode",
-            });
-            qpOpiton.title = "正在登录中文版leetcode.cn";
-            qpOpiton.placeHolder = "请选择登录方式 正在登录中文版leetcode.cn";
-        }
-        picks.push(
-            {
-                label: "Third-Party: GitHub",
-                detail: "Use GitHub account to login",
-                value: "GitHub",
-            },
-            {
-                label: "Third-Party: LinkedIn",
-                detail: "Use LinkedIn account to login",
-                value: "LinkedIn",
-            },
-            {
-                label: "LeetCode Cookie",
-                detail: "Use LeetCode cookie copied from browser to login",
-                value: "Cookie",
-            },
-        );
-        const choice: IQuickItemEx | undefined = await window.showQuickPick(picks, qpOpiton);
-        if (!choice) {
-            return;
-        }
-        const loginMethod: string = choice.value;
-        const commandArg: string | undefined = loginArgsMapping.get(loginMethod);
-        if (!commandArg) {
-            throw new Error(`不支持 "${loginMethod}" 方式登录`);
-        }
-        const isByCookie: boolean = loginMethod === "Cookie";
-        const inMessage: string = isByCookie ? " 通过cookie登录" : "登录";
-        try {
-            const userName: string | undefined = await new Promise(async (resolve: (res: string | undefined) => void, reject: (e: Error) => void): Promise => {
-
-                const leetCodeBinaryPath: string = await executeService.getLeetCodeBinaryPath();
-
-                let childProc: cp.ChildProcess;
-
-                if (systemUtils.useVscodeNode()) {
-                    childProc = cp.fork(await executeService.getLeetCodeBinaryPath(), ["user", commandArg], {
-                        silent: true,
-                        env: createEnvOption(),
-                    });
-                } else {
-                    if (systemUtils.useWsl()) {
-                        childProc = cp.spawn("wsl", [executeService.node, leetCodeBinaryPath, "user", commandArg], { shell: true });
-                    } else {
-                        childProc = cp.spawn(executeService.node, [leetCodeBinaryPath, "user", commandArg], {
-                            shell: true,
-                            env: createEnvOption(),
-                        });
-                    }
-
-                }
-
-                childProc.stdout?.on("data", async (data: string | Buffer) => {
-                    data = data.toString();
-                    // vscode.window.showInformationMessage(`cc login msg ${data}.`);
-                    logOutput.append(data);
-                    if (data.includes("twoFactorCode")) {
-                        const twoFactor: string | undefined = await window.showInputBox({
-                            prompt: "Enter two-factor code.",
-                            ignoreFocusOut: true,
-                            validateInput: (s: string): string | undefined => s && s.trim() ? undefined : "The input must not be empty",
-                        });
-                        if (!twoFactor) {
-                            childProc.kill();
-                            return resolve(undefined);
-                        }
-                        childProc.stdin?.write(`${twoFactor}\n`);
-                    }
-
-                    let successMatch;
-                    try {
-                        successMatch = JSON.parse(data);
-                    } catch (e) {
-                        successMatch = {};
-                    }
-                    if (successMatch.code == 100) {
-                        childProc.stdin?.end();
-                        return resolve(successMatch.user_name);
-                    } else if (successMatch.code < 0) {
-                        childProc.stdin?.end();
-                        return reject(new Error(successMatch.msg));
-                    }
-                });
-
-                childProc.stderr?.on("data", (data: string | Buffer) => logOutput.append(data.toString()));
-
-                childProc.on("error", reject);
-                const name: string | undefined = await window.showInputBox({
-                    prompt: "Enter username or E-mail.",
-                    ignoreFocusOut: true,
-                    validateInput: (s: string): string | undefined => s && s.trim() ? undefined : "The input must not be empty",
-                });
-                if (!name) {
-                    childProc.kill();
-                    return resolve(undefined);
-                }
-                childProc.stdin?.write(`${name}\n`);
-                const pwd: string | undefined = await window.showInputBox({
-                    prompt: isByCookie ? "Enter cookie" : "Enter password.",
-                    password: true,
-                    ignoreFocusOut: true,
-                    validateInput: (s: string): string | undefined => s ? undefined : isByCookie ? "Cookie must not be empty" : "Password must not be empty",
-                });
-                if (!pwd) {
-                    childProc.kill();
-                    return resolve(undefined);
-                }
-                childProc.stdin?.write(`${pwd}\n`);
+  constructor() {}
+
+  // 登录操作
+  public async signIn(): Promise {
+    const picks: Array> = [];
+    let qpOpiton: QuickPickOptions = {
+      title: "正在登录leetcode.com",
+      matchOnDescription: false,
+      matchOnDetail: false,
+      placeHolder: "请选择登录方式 正在登录leetcode.com",
+    };
+    if (getLeetCodeEndpoint() == Endpoint.LeetCodeCN) {
+      picks.push({
+        label: "LeetCode Account",
+        detail: "只能登录leetcode.cn",
+        value: "LeetCode",
+      });
+      qpOpiton.title = "正在登录中文版leetcode.cn";
+      qpOpiton.placeHolder = "请选择登录方式 正在登录中文版leetcode.cn";
+    }
+    picks.push(
+      {
+        label: "Third-Party: GitHub",
+        detail: "Use GitHub account to login",
+        value: "GitHub",
+      },
+      {
+        label: "Third-Party: LinkedIn",
+        detail: "Use LinkedIn account to login",
+        value: "LinkedIn",
+      },
+      {
+        label: "LeetCode Cookie",
+        detail: "Use LeetCode cookie copied from browser to login",
+        value: "Cookie",
+      }
+    );
+    const choice: IQuickItemEx | undefined = await window.showQuickPick(picks, qpOpiton);
+    if (!choice) {
+      return;
+    }
+    const loginMethod: string = choice.value;
+    const commandArg: string | undefined = loginArgsMapping.get(loginMethod);
+    if (!commandArg) {
+      throw new Error(`不支持 "${loginMethod}" 方式登录`);
+    }
+    const isByCookie: boolean = loginMethod === "Cookie";
+    const inMessage: string = isByCookie ? " 通过cookie登录" : "登录";
+    try {
+      const userName: string | undefined = await new Promise(
+        async (resolve: (res: string | undefined) => void, reject: (e: Error) => void): Promise => {
+          const leetCodeBinaryPath: string = await executeService.getLeetCodeBinaryPath();
+
+          let childProc: cp.ChildProcess;
+
+          if (systemUtils.useVscodeNode()) {
+            childProc = cp.fork(await executeService.getLeetCodeBinaryPath(), ["user", commandArg], {
+              silent: true,
+              env: createEnvOption(),
             });
-            if (userName) {
-                window.showInformationMessage(`${inMessage} 成功`);
-                eventService.emit("statusChanged", UserStatus.SignedIn, userName);
+          } else {
+            if (systemUtils.useWsl()) {
+              childProc = cp.spawn("wsl", [executeService.node, leetCodeBinaryPath, "user", commandArg], {
+                shell: true,
+              });
+            } else {
+              childProc = cp.spawn(executeService.node, [leetCodeBinaryPath, "user", commandArg], {
+                shell: true,
+                env: createEnvOption(),
+              });
+            }
+          }
+
+          childProc.stdout?.on("data", async (data: string | Buffer) => {
+            data = data.toString();
+            // vscode.window.showInformationMessage(`cc login msg ${data}.`);
+            logOutput.append(data);
+            if (data.includes("twoFactorCode")) {
+              const twoFactor: string | undefined = await window.showInputBox({
+                prompt: "Enter two-factor code.",
+                ignoreFocusOut: true,
+                validateInput: (s: string): string | undefined =>
+                  s && s.trim() ? undefined : "The input must not be empty",
+              });
+              if (!twoFactor) {
+                childProc.kill();
+                return resolve(undefined);
+              }
+              childProc.stdin?.write(`${twoFactor}\n`);
             }
-        } catch (error) {
-            promptForOpenOutputChannel(`${inMessage}失败. 请看看控制台输出信息`, DialogType.error);
-        }
-
-    }
 
-    // 登出
-    public async signOut(): Promise {
-        try {
-            await executeService.signOut();
-            window.showInformationMessage("成功登出");
-            eventService.emit("statusChanged", UserStatus.SignedOut, undefined);
-        } catch (error) {
-            // promptForOpenOutputChannel(`Failed to signOut. Please open the output channel for details`, DialogType.error);
+            let successMatch;
+            try {
+              successMatch = JSON.parse(data);
+            } catch (e) {
+              successMatch = {};
+            }
+            if (successMatch.code == 100) {
+              childProc.stdin?.end();
+              return resolve(successMatch.user_name);
+            } else if (successMatch.code < 0) {
+              childProc.stdin?.end();
+              return reject(new Error(successMatch.msg));
+            }
+          });
+
+          childProc.stderr?.on("data", (data: string | Buffer) => logOutput.append(data.toString()));
+
+          childProc.on("error", reject);
+          const name: string | undefined = await window.showInputBox({
+            prompt: "Enter username or E-mail.",
+            ignoreFocusOut: true,
+            validateInput: (s: string): string | undefined =>
+              s && s.trim() ? undefined : "The input must not be empty",
+          });
+          if (!name) {
+            childProc.kill();
+            return resolve(undefined);
+          }
+          childProc.stdin?.write(`${name}\n`);
+          const pwd: string | undefined = await window.showInputBox({
+            prompt: isByCookie ? "Enter cookie" : "Enter password.",
+            password: true,
+            ignoreFocusOut: true,
+            validateInput: (s: string): string | undefined =>
+              s ? undefined : isByCookie ? "Cookie must not be empty" : "Password must not be empty",
+          });
+          if (!pwd) {
+            childProc.kill();
+            return resolve(undefined);
+          }
+          childProc.stdin?.write(`${pwd}\n`);
         }
+      );
+      if (userName) {
+        eventService.emit("statusChanged", UserStatus.SignedIn, userName);
+        window.showInformationMessage(`${inMessage} 成功`);
+      }
+    } catch (error) {
+      promptForOpenOutputChannel(`${inMessage}失败. 请看看控制台输出信息`, DialogType.error);
     }
-
-    // 获取登录状态
-    public async getLoginStatus() {
-        return await statusBarService.getLoginStatus();
-    }
-
-    // 删除所有缓存
-    public async deleteAllCache(): Promise {
-        await this.signOut();
-        await executeService.removeOldCache();
-        await executeService.switchEndpoint(getLeetCodeEndpoint());
-        await treeDataService.refresh();
+  }
+
+  // 登出
+  public async signOut(): Promise {
+    try {
+      await executeService.signOut();
+      window.showInformationMessage("成功登出");
+      eventService.emit("statusChanged", UserStatus.SignedOut, undefined);
+    } catch (error) {
+      // promptForOpenOutputChannel(`Failed to signOut. Please open the output channel for details`, DialogType.error);
     }
-
+  }
+
+  // 获取登录状态
+  public async getLoginStatus() {
+    return await statusBarService.getLoginStatus();
+  }
+
+  // 删除所有缓存
+  public async deleteAllCache(): Promise {
+    await this.signOut();
+    await executeService.removeOldCache();
+    await executeService.switchEndpoint(getLeetCodeEndpoint());
+    await treeDataService.refresh();
+  }
 }
 
 export const loginContorller: LoginContorller = new LoginContorller();
diff --git a/src/controller/MainController.ts b/src/controller/MainController.ts
index f5abdaa..d8a0ddf 100644
--- a/src/controller/MainController.ts
+++ b/src/controller/MainController.ts
@@ -11,32 +11,44 @@ import * as systemUtils from "../utils/SystemUtils";
 import { executeService } from "../service/ExecuteService";
 import { ExtensionContext } from "vscode";
 import { treeDataService } from "../service/TreeDataService";
+import { logOutput } from "../utils/OutputUtils";
 
 // 做杂活
 class MainContorller {
-    constructor() { }
+  constructor() {}
 
-    /**
-     * 检查运行环境
-     */
-    public async checkNodeEnv(context: ExtensionContext) {
-        if (!systemUtils.useVscodeNode()) {
-            if (!await executeService.checkNodeEnv(context)) {
-                throw new Error("The environment doesn't meet requirements.");
-            }
-        }
+  /**
+   * 检查运行环境
+   */
+  public async checkNodeEnv(context: ExtensionContext) {
+    if (!systemUtils.useVscodeNode()) {
+      if (!(await executeService.checkNodeEnv(context))) {
+        throw new Error("The environment doesn't meet requirements.");
+      }
     }
+  }
 
-    // 初始化上下文
-    public initialize(context: ExtensionContext) {
-        treeDataService.initialize(context);
-    }
+  public setGlobal(context: ExtensionContext) {
+    let cur_version: string = context.extension.packageJSON.version || "1.0.0";
+    let cur_version_arr: Array = cur_version.split(".");
+    let cur_version_num = 0;
+    cur_version_arr.forEach((e) => {
+      cur_version_num *= 100;
+      cur_version_num += Number(e);
+    });
+    logOutput.setLCPTCTX("version", cur_version_num);
+  }
 
+  // 初始化上下文
+  public initialize(context: ExtensionContext) {
+    this.setGlobal(context);
+    treeDataService.initialize(context);
+  }
 
-    // 删除缓存
-    public async deleteCache() {
-        await executeService.deleteCache();
-    }
+  // 删除缓存
+  public async deleteCache() {
+    await executeService.deleteCache();
+  }
 }
 
 export const mainContorller: MainContorller = new MainContorller();
diff --git a/src/controller/TreeViewController.ts b/src/controller/TreeViewController.ts
index 33df1ce..2122112 100644
--- a/src/controller/TreeViewController.ts
+++ b/src/controller/TreeViewController.ts
@@ -7,15 +7,48 @@
  * Copyright (c) 2022 ccagml . All rights reserved.
  */
 
-
 import * as lodash from "lodash";
 import * as path from "path";
 import * as unescapeJS from "unescape-js";
 import * as vscode from "vscode";
 import { toNumber } from "lodash";
 import { Disposable, Uri, window, QuickPickItem, workspace, WorkspaceConfiguration } from "vscode";
-import { SearchNode, userContestRankingObj, userContestRanKingBase, UserStatus, IProblem, IQuickItemEx, languages, Category, defaultProblem, ProblemState, SortingStrategy, SearchSetTypeName, RootNodeSort, SearchSetType, ISubmitEvent, SORT_ORDER, Endpoint, OpenOption, DialogType, DialogOptions } from "../model/Model";
-import { isHideSolvedProblem, isHideScoreProblem, getDescriptionConfiguration, isUseEndpointTranslation, enableSideMode, getPickOneByRankRangeMin, getPickOneByRankRangeMax, isShowLocked, updateSortingStrategy, getSortingStrategy, getLeetCodeEndpoint, openSettingsEditor } from "../utils/ConfigUtils";
+import {
+  SearchNode,
+  userContestRankingObj,
+  userContestRanKingBase,
+  UserStatus,
+  IProblem,
+  IQuickItemEx,
+  languages,
+  Category,
+  defaultProblem,
+  ProblemState,
+  SortingStrategy,
+  SearchSetTypeName,
+  RootNodeSort,
+  SearchSetType,
+  ISubmitEvent,
+  SORT_ORDER,
+  Endpoint,
+  OpenOption,
+  DialogType,
+  DialogOptions,
+} from "../model/Model";
+import {
+  isHideSolvedProblem,
+  isHideScoreProblem,
+  getDescriptionConfiguration,
+  isUseEndpointTranslation,
+  enableSideMode,
+  getPickOneByRankRangeMin,
+  getPickOneByRankRangeMax,
+  isShowLocked,
+  updateSortingStrategy,
+  getSortingStrategy,
+  getLeetCodeEndpoint,
+  openSettingsEditor,
+} from "../utils/ConfigUtils";
 import { NodeModel } from "../model/NodeModel";
 import { ISearchSet } from "../model/Model";
 import { statusBarService } from "../service/StatusBarService";
@@ -34,1422 +67,1542 @@ import { fileButtonService } from "../service/FileButtonService";
 import * as fse from "fs-extra";
 import { submissionService } from "../service/SubmissionService";
 
-
 import * as os from "os";
 import { getVsCodeConfig, getWorkspaceFolder } from "../utils/ConfigUtils";
 
-
 // 视图控制器
 class TreeViewController implements Disposable {
-    private explorerNodeMap: Map = new Map();
-    private companySet: Set = new Set();
-    private tagSet: Set = new Set();
-    private searchSet: Map = new Map();
-    private waitTodayQuestion: boolean;
-    private waitUserContest: boolean;
-
-    // 获取当前文件的路径
-    public async getActiveFilePath(uri?: vscode.Uri): Promise {
-        let textEditor: vscode.TextEditor | undefined;
-        if (uri) {
-            textEditor = await vscode.window.showTextDocument(uri, { preview: false });
-        } else {
-            textEditor = vscode.window.activeTextEditor;
-        }
-
-        if (!textEditor) {
-            return undefined;
-        }
-        if (textEditor.document.isDirty && !await textEditor.document.save()) {
-            vscode.window.showWarningMessage("请先保存当前文件");
-            return undefined;
-        }
-        return systemUtils.useWsl() ? systemUtils.toWslPath(textEditor.document.uri.fsPath) : textEditor.document.uri.fsPath;
+  private explorerNodeMap: Map = new Map();
+  private companySet: Set = new Set();
+  private tagSet: Set = new Set();
+  private searchSet: Map = new Map();
+  private waitTodayQuestion: boolean;
+  private waitUserContest: boolean;
+
+  // 获取当前文件的路径
+  public async getActiveFilePath(uri?: vscode.Uri): Promise {
+    let textEditor: vscode.TextEditor | undefined;
+    if (uri) {
+      textEditor = await vscode.window.showTextDocument(uri, {
+        preview: false,
+      });
+    } else {
+      textEditor = vscode.window.activeTextEditor;
     }
 
-    // 提交问题
-    public async submitSolution(uri?: vscode.Uri): Promise {
-        if (!statusBarService.getUser()) {
-            promptForSignIn();
-            return;
-        }
-
-        const filePath: string | undefined = await this.getActiveFilePath(uri);
-        if (!filePath) {
-            return;
-        }
-
-        try {
-            const result: string = await executeService.submitSolution(filePath);
-            submissionService.show(result);
-            eventService.emit("submit", submissionService.getSubmitEvent());
-        } catch (error) {
-            await promptForOpenOutputChannel("提交出错了. 请查看控制台信息~", DialogType.error);
-            return;
-        }
-
-        treeDataService.refresh();
+    if (!textEditor) {
+      return undefined;
     }
-
-
-    // 提交测试用例
-    public async testSolution(uri?: vscode.Uri): Promise {
-        try {
-            if (statusBarService.getStatus() === UserStatus.SignedOut) {
-                return;
-            }
-
-            const filePath: string | undefined = await this.getActiveFilePath(uri);
-            if (!filePath) {
-                return;
-            }
-            const picks: Array> = [];
-            picks.push(
-                // {
-                //     label: "$(three-bars) Default test cases",
-                //     description: "",
-                //     detail: "默认用例",
-                //     value: ":default",
-                // },
-                {
-                    label: "$(pencil) Write directly...",
-                    description: "",
-                    detail: "输入框的测试用例",
-                    value: ":direct",
-                },
-                {
-                    label: "$(file-text) Browse...",
-                    description: "",
-                    detail: "文件中的测试用例",
-                    value: ":file",
-                },
-                // {
-                //     label: "All Default test cases...",
-                //     description: "",
-                //     detail: "所有的测试用例",
-                //     value: ":alldefault",
-                // },
-            );
-            const choice: IQuickItemEx | undefined = await vscode.window.showQuickPick(picks);
-            if (!choice) {
-                return;
-            }
-
-            let result: string | undefined;
-            let testString: string | undefined;
-            let testFile: vscode.Uri[] | undefined;
-            switch (choice.value) {
-                case ":default":
-                    result = await executeService.testSolution(filePath);
-                    break;
-                case ":direct":
-                    testString = await vscode.window.showInputBox({
-                        prompt: "Enter the test cases.",
-                        validateInput: (s: string): string | undefined => s && s.trim() ? undefined : "Test case must not be empty.",
-                        placeHolder: "Example: [1,2,3]\\n4",
-                        ignoreFocusOut: true,
-                    });
-                    if (testString) {
-                        result = await executeService.testSolution(filePath, this.parseTestString(testString));
-                    }
-                    break;
-                case ":file":
-                    testFile = await this.showFileSelectDialog(filePath);
-                    if (testFile && testFile.length) {
-                        const input: string = (await fse.readFile(testFile[0].fsPath, "utf-8")).trim();
-                        if (input) {
-                            result = await executeService.testSolution(filePath, this.parseTestString(input.replace(/\r?\n/g, "\\n")));
-                        } else {
-                            vscode.window.showErrorMessage("The selected test file must not be empty.");
-                        }
-                    }
-                    break;
-                case ":alldefault":
-                    result = await executeService.testSolution(filePath, undefined, true);
-                    break;
-                default:
-                    break;
-            }
-            if (!result) {
-                return;
-            }
-            submissionService.show(result);
-            eventService.emit("submit", submissionService.getSubmitEvent());
-        } catch (error) {
-            await promptForOpenOutputChannel("提交测试出错了. 请查看控制台信息~", DialogType.error);
-        }
+    if (textEditor.document.isDirty && !(await textEditor.document.save())) {
+      vscode.window.showWarningMessage("请先保存当前文件");
+      return undefined;
     }
-    public async showFileSelectDialog(fsPath?: string): Promise {
-        const defaultUri: vscode.Uri | undefined = this.getBelongingWorkspaceFolderUri(fsPath);
-        const options: vscode.OpenDialogOptions = {
-            defaultUri,
-            canSelectFiles: true,
-            canSelectFolders: false,
-            canSelectMany: false,
-            openLabel: "Select",
-        };
-        return await vscode.window.showOpenDialog(options);
+    return systemUtils.useWsl()
+      ? systemUtils.toWslPath(textEditor.document.uri.fsPath)
+      : textEditor.document.uri.fsPath;
+  }
+
+  // 提交问题
+  public async submitSolution(uri?: vscode.Uri): Promise {
+    if (!statusBarService.getUser()) {
+      promptForSignIn();
+      return;
     }
 
-
-    public async testSolutionDefault(uri?: vscode.Uri, allCase?: boolean): Promise {
-        try {
-            if (statusBarService.getStatus() === UserStatus.SignedOut) {
-                return;
-            }
-
-            const filePath: string | undefined = await this.getActiveFilePath(uri);
-            if (!filePath) {
-                return;
-            }
-
-            let result: string | undefined = await executeService.testSolution(filePath, undefined, allCase || false);
-            if (!result) {
-                return;
-            }
-            submissionService.show(result);
-            eventService.emit("submit", submissionService.getSubmitEvent());
-        } catch (error) {
-            await promptForOpenOutputChannel("提交测试出错了. 请查看控制台信息~", DialogType.error);
-        }
+    const filePath: string | undefined = await this.getActiveFilePath(uri);
+    if (!filePath) {
+      return;
     }
 
-    public usingCmd(): boolean {
-        const comSpec: string | undefined = process.env.ComSpec;
-        // 'cmd.exe' is used as a fallback if process.env.ComSpec is unavailable.
-        if (!comSpec) {
-            return true;
-        }
-
-        if (comSpec.indexOf("cmd.exe") > -1) {
-            return true;
-        }
-        return false;
+    try {
+      const result: string = await executeService.submitSolution(filePath);
+      submissionService.show(result);
+      eventService.emit("submit", submissionService.getSubmitEvent());
+    } catch (error) {
+      await promptForOpenOutputChannel("提交出错了. 请查看控制台信息~", DialogType.error);
+      return;
     }
 
-    public parseTestString(test: string): string {
-        if (systemUtils.useWsl() || !systemUtils.isWindows()) {
-            if (systemUtils.useVscodeNode()) {
-                return `${test}`;
-            }
-            return `'${test}'`;
-        }
-
-        if (this.usingCmd()) {
-            // 一般需要走进这里, 除非改了 环境变量ComSpec的值
-            if (systemUtils.useVscodeNode()) {
-                //eslint-disable-next-line
-                return `${test.replace(/"/g, '\"')}`;
-            }
-            return `"${test.replace(/"/g, '\\"')}"`;
-        } else {
-            if (systemUtils.useVscodeNode()) {
-                //eslint-disable-next-line
-                return `${test.replace(/"/g, '\"')}`;
+    treeDataService.refresh();
+  }
+
+  // 提交测试用例
+  public async testSolution(uri?: vscode.Uri): Promise {
+    try {
+      if (statusBarService.getStatus() === UserStatus.SignedOut) {
+        return;
+      }
+
+      const filePath: string | undefined = await this.getActiveFilePath(uri);
+      if (!filePath) {
+        return;
+      }
+      const picks: Array> = [];
+      picks.push(
+        // {
+        //     label: "$(three-bars) Default test cases",
+        //     description: "",
+        //     detail: "默认用例",
+        //     value: ":default",
+        // },
+        {
+          label: "$(pencil) Write directly...",
+          description: "",
+          detail: "输入框的测试用例",
+          value: ":direct",
+        },
+        {
+          label: "$(file-text) Browse...",
+          description: "",
+          detail: "文件中的测试用例",
+          value: ":file",
+        }
+        // {
+        //     label: "All Default test cases...",
+        //     description: "",
+        //     detail: "所有的测试用例",
+        //     value: ":alldefault",
+        // },
+      );
+      const choice: IQuickItemEx | undefined = await vscode.window.showQuickPick(picks);
+      if (!choice) {
+        return;
+      }
+
+      let result: string | undefined;
+      let testString: string | undefined;
+      let testFile: vscode.Uri[] | undefined;
+      switch (choice.value) {
+        case ":default":
+          result = await executeService.testSolution(filePath);
+          break;
+        case ":direct":
+          testString = await vscode.window.showInputBox({
+            prompt: "Enter the test cases.",
+            validateInput: (s: string): string | undefined =>
+              s && s.trim() ? undefined : "Test case must not be empty.",
+            placeHolder: "Example: [1,2,3]\\n4",
+            ignoreFocusOut: true,
+          });
+          if (testString) {
+            result = await executeService.testSolution(filePath, this.parseTestString(testString));
+          }
+          break;
+        case ":file":
+          testFile = await this.showFileSelectDialog(filePath);
+          if (testFile && testFile.length) {
+            const input: string = (await fse.readFile(testFile[0].fsPath, "utf-8")).trim();
+            if (input) {
+              result = await executeService.testSolution(
+                filePath,
+                this.parseTestString(input.replace(/\r?\n/g, "\\n"))
+              );
+            } else {
+              vscode.window.showErrorMessage("The selected test file must not be empty.");
             }
-            return `'${test.replace(/"/g, '\\"')}'`;
-        }
+          }
+          break;
+        case ":alldefault":
+          result = await executeService.testSolution(filePath, undefined, true);
+          break;
+        default:
+          break;
+      }
+      if (!result) {
+        return;
+      }
+      submissionService.show(result);
+      eventService.emit("submit", submissionService.getSubmitEvent());
+    } catch (error) {
+      await promptForOpenOutputChannel("提交测试出错了. 请查看控制台信息~", DialogType.error);
     }
-
-
-    public async switchEndpoint(): Promise {
-        const isCnEnabled: boolean = getLeetCodeEndpoint() === Endpoint.LeetCodeCN;
-        const picks: Array> = [];
-        picks.push(
-            {
-                label: `${isCnEnabled ? "" : "$(check) "}LeetCode`,
-                description: "leetcode.com",
-                detail: `Enable LeetCode.com US`,
-                value: Endpoint.LeetCode,
-            },
-            {
-                label: `${isCnEnabled ? "$(check) " : ""}力扣`,
-                description: "leetcode.cn",
-                detail: `启用中国版 LeetCode.cn`,
-                value: Endpoint.LeetCodeCN,
-            },
-        );
-        const choice: IQuickItemEx | undefined = await vscode.window.showQuickPick(picks);
-        if (!choice || choice.value === getLeetCodeEndpoint()) {
-            return;
-        }
-        const leetCodeConfig: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("leetcode-problem-rating");
-        try {
-            const endpoint: string = choice.value;
-            await executeService.switchEndpoint(endpoint);
-            await leetCodeConfig.update("endpoint", endpoint, true /* UserSetting */);
-            vscode.window.showInformationMessage(`Switched the endpoint to ${endpoint}`);
-        } catch (error) {
-            await promptForOpenOutputChannel("切换站点出错. 请查看控制台信息~", DialogType.error);
-        }
-
-        try {
-            await vscode.commands.executeCommand("leetcode.signout");
-            await executeService.deleteCache();
-            await promptForSignIn();
-        } catch (error) {
-            await promptForOpenOutputChannel("登录失败. 请查看控制台信息~", DialogType.error);
-        }
+  }
+  public async showFileSelectDialog(fsPath?: string): Promise {
+    const defaultUri: vscode.Uri | undefined = this.getBelongingWorkspaceFolderUri(fsPath);
+    const options: vscode.OpenDialogOptions = {
+      defaultUri,
+      canSelectFiles: true,
+      canSelectFolders: false,
+      canSelectMany: false,
+      openLabel: "Select",
+    };
+    return await vscode.window.showOpenDialog(options);
+  }
+
+  public async testSolutionDefault(uri?: vscode.Uri, allCase?: boolean): Promise {
+    try {
+      if (statusBarService.getStatus() === UserStatus.SignedOut) {
+        return;
+      }
+
+      const filePath: string | undefined = await this.getActiveFilePath(uri);
+      if (!filePath) {
+        return;
+      }
+
+      let result: string | undefined = await executeService.testSolution(filePath, undefined, allCase || false);
+      if (!result) {
+        return;
+      }
+      submissionService.show(result);
+      eventService.emit("submit", submissionService.getSubmitEvent());
+    } catch (error) {
+      await promptForOpenOutputChannel("提交测试出错了. 请查看控制台信息~", DialogType.error);
     }
-
-
-    public async switchSortingStrategy(): Promise {
-        const currentStrategy: SortingStrategy = getSortingStrategy();
-        const picks: Array> = [];
-        picks.push(
-            ...SORT_ORDER.map((s: SortingStrategy) => {
-                return {
-                    label: `${currentStrategy === s ? "$(check)" : "    "} ${s}`,
-                    value: s,
-                };
-            }),
-        );
-
-        const choice: IQuickItemEx | undefined = await vscode.window.showQuickPick(picks);
-        if (!choice || choice.value === currentStrategy) {
-            return;
-        }
-
-        await updateSortingStrategy(choice.value, true);
-        await treeDataService.refresh();
+  }
+
+  public async testSolutionArea(uri?: vscode.Uri, testcase?: string): Promise {
+    try {
+      if (statusBarService.getStatus() === UserStatus.SignedOut) {
+        return;
+      }
+
+      const filePath: string | undefined = await this.getActiveFilePath(uri);
+      if (!filePath) {
+        return;
+      }
+
+      let result: string | undefined = await executeService.testSolution(filePath, testcase, false);
+      if (!result) {
+        return;
+      }
+      submissionService.show(result);
+      eventService.emit("submit", submissionService.getSubmitEvent());
+    } catch (error) {
+      await promptForOpenOutputChannel("提交测试出错了. 请查看控制台信息~", DialogType.error);
     }
+  }
 
-
-    public async addFavorite(node: NodeModel): Promise {
-        try {
-            await executeService.toggleFavorite(node, true);
-            await treeDataService.refresh();
-            if (isStarShortcut()) {
-                fileButtonService.refresh();
-            }
-        } catch (error) {
-            await promptForOpenOutputChannel("添加喜欢题目失败. 请查看控制台信息~", DialogType.error);
-        }
+  public usingCmd(): boolean {
+    const comSpec: string | undefined = process.env.ComSpec;
+    // 'cmd.exe' is used as a fallback if process.env.ComSpec is unavailable.
+    if (!comSpec) {
+      return true;
     }
 
-    public async removeFavorite(node: NodeModel): Promise {
-        try {
-            await executeService.toggleFavorite(node, false);
-            await treeDataService.refresh();
-            if (isStarShortcut()) {
-                fileButtonService.refresh();
-            }
-        } catch (error) {
-            await promptForOpenOutputChannel("移除喜欢题目失败. 请查看控制台信息~", DialogType.error);
-        }
+    if (comSpec.indexOf("cmd.exe") > -1) {
+      return true;
     }
-
-    public async listProblems(): Promise {
-        try {
-            if (statusBarService.getStatus() === UserStatus.SignedOut) {
-                return [];
-            }
-
-            const showLockedFlag: boolean = isShowLocked();
-            const useEndpointTranslation: boolean = isUseEndpointTranslation();
-            const result: string = await executeService.listProblems(showLockedFlag, useEndpointTranslation);
-            const all_problem_info = JSON.parse(result);
-            const problems: IProblem[] = [];
-            const AllScoreData = treeDataService.getScoreData();
-            // 增加直接在线获取分数数据
-            const AllScoreDataOnline = await treeDataService.getScoreDataOnline();
-            for (const p of all_problem_info) {
-                problems.push({
-                    id: p.fid,
-                    qid: p.id,
-                    isFavorite: p.starred,
-                    locked: p.locked,
-                    state: this.parseProblemState(p.state),
-                    name: p.name,
-                    difficulty: p.level,
-                    passRate: p.percent,
-                    companies: p.companies || [],
-                    tags: treeDataService.getTagsData(p.fid),
-                    scoreData: AllScoreDataOnline.get(p.fid) || AllScoreData.get(p.fid),
-                    isSearchResult: false,
-                    input: "",
-                    rootNodeSortId: RootNodeSort.ZERO,
-                    todayData: undefined,
-                });
-            }
-            return problems.reverse();
-        } catch (error) {
-            await promptForOpenOutputChannel("获取题目失败. 请查看控制台信息~", DialogType.error);
-            return [];
-        }
+    return false;
+  }
+
+  public parseTestString(test: string): string {
+    if (systemUtils.useWsl() || !systemUtils.isWindows()) {
+      if (systemUtils.useVscodeNode()) {
+        return `${test}`;
+      }
+      return `'${test}'`;
     }
 
-    public parseProblemState(stateOutput: string): ProblemState {
-        if (!stateOutput) {
-            return ProblemState.Unknown;
-        }
-        switch (stateOutput.trim()) {
-            case "v":
-            case "✔":
-            case "√":
-            case "ac":
-                return ProblemState.AC;
-            case "X":
-            case "✘":
-            case "×":
-            case "notac":
-                return ProblemState.NotAC;
-            default:
-                return ProblemState.Unknown;
-        }
+    if (this.usingCmd()) {
+      // 一般需要走进这里, 除非改了 环境变量ComSpec的值
+      if (systemUtils.useVscodeNode()) {
+        //eslint-disable-next-line
+        return `${test.replace(/"/g, '"')}`;
+      }
+      return `"${test.replace(/"/g, '\\"')}"`;
+    } else {
+      if (systemUtils.useVscodeNode()) {
+        //eslint-disable-next-line
+        return `${test.replace(/"/g, '"')}`;
+      }
+      return `'${test.replace(/"/g, '\\"')}'`;
+    }
+  }
+
+  public async switchEndpoint(): Promise {
+    const isCnEnabled: boolean = getLeetCodeEndpoint() === Endpoint.LeetCodeCN;
+    const picks: Array> = [];
+    picks.push(
+      {
+        label: `${isCnEnabled ? "" : "$(check) "}LeetCode`,
+        description: "leetcode.com",
+        detail: `Enable LeetCode.com US`,
+        value: Endpoint.LeetCode,
+      },
+      {
+        label: `${isCnEnabled ? "$(check) " : ""}力扣`,
+        description: "leetcode.cn",
+        detail: `启用中国版 LeetCode.cn`,
+        value: Endpoint.LeetCodeCN,
+      }
+    );
+    const choice: IQuickItemEx | undefined = await vscode.window.showQuickPick(picks);
+    if (!choice || choice.value === getLeetCodeEndpoint()) {
+      return;
+    }
+    const leetCodeConfig: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("leetcode-problem-rating");
+    try {
+      const endpoint: string = choice.value;
+      await executeService.switchEndpoint(endpoint);
+      await leetCodeConfig.update("endpoint", endpoint, true /* UserSetting */);
+      vscode.window.showInformationMessage(`Switched the endpoint to ${endpoint}`);
+    } catch (error) {
+      await promptForOpenOutputChannel("切换站点出错. 请查看控制台信息~", DialogType.error);
     }
 
+    try {
+      await vscode.commands.executeCommand("leetcode.signout");
+      await executeService.deleteCache();
+      await promptForSignIn();
+    } catch (error) {
+      await promptForOpenOutputChannel("登录失败. 请查看控制台信息~", DialogType.error);
+    }
+  }
+
+  public async switchSortingStrategy(): Promise {
+    const currentStrategy: SortingStrategy = getSortingStrategy();
+    const picks: Array> = [];
+    picks.push(
+      ...SORT_ORDER.map((s: SortingStrategy) => {
+        return {
+          label: `${currentStrategy === s ? "$(check)" : "    "} ${s}`,
+          value: s,
+        };
+      })
+    );
 
-    public async switchDefaultLanguage(): Promise {
-        const leetCodeConfig: WorkspaceConfiguration = workspace.getConfiguration("leetcode-problem-rating");
-        const defaultLanguage: string | undefined = leetCodeConfig.get("defaultLanguage");
-        const languageItems: QuickPickItem[] = [];
-        for (const language of languages) {
-            languageItems.push({
-                label: language,
-                description: defaultLanguage === language ? "Currently used" : undefined,
-            });
-        }
-        // Put the default language at the top of the list
-        languageItems.sort((a: QuickPickItem, b: QuickPickItem) => {
-            if (a.description) {
-                return Number.MIN_SAFE_INTEGER;
-            } else if (b.description) {
-                return Number.MAX_SAFE_INTEGER;
-            }
-            return a.label.localeCompare(b.label);
-        });
+    const choice: IQuickItemEx | undefined = await vscode.window.showQuickPick(picks);
+    if (!choice || choice.value === currentStrategy) {
+      return;
+    }
 
-        const selectedItem: QuickPickItem | undefined = await window.showQuickPick(languageItems, {
-            placeHolder: "请设置默认语言",
-            ignoreFocusOut: true,
+    await updateSortingStrategy(choice.value, true);
+    await treeDataService.refresh();
+  }
+
+  public async addFavorite(node: NodeModel): Promise {
+    try {
+      await executeService.toggleFavorite(node, true);
+      await treeDataService.refresh();
+      if (isStarShortcut()) {
+        fileButtonService.refresh();
+      }
+    } catch (error) {
+      await promptForOpenOutputChannel("添加喜欢题目失败. 请查看控制台信息~", DialogType.error);
+    }
+  }
+
+  public async removeFavorite(node: NodeModel): Promise {
+    try {
+      await executeService.toggleFavorite(node, false);
+      await treeDataService.refresh();
+      if (isStarShortcut()) {
+        fileButtonService.refresh();
+      }
+    } catch (error) {
+      await promptForOpenOutputChannel("移除喜欢题目失败. 请查看控制台信息~", DialogType.error);
+    }
+  }
+
+  public async listProblems(): Promise {
+    try {
+      if (statusBarService.getStatus() === UserStatus.SignedOut) {
+        return [];
+      }
+
+      const showLockedFlag: boolean = isShowLocked();
+      const useEndpointTranslation: boolean = isUseEndpointTranslation();
+      const result: string = await executeService.listProblems(showLockedFlag, useEndpointTranslation);
+      const all_problem_info = JSON.parse(result);
+      const problems: IProblem[] = [];
+      const AllScoreData = treeDataService.getScoreData();
+      // 增加直接在线获取分数数据
+      const AllScoreDataOnline = await treeDataService.getScoreDataOnline();
+      for (const p of all_problem_info) {
+        problems.push({
+          id: p.fid,
+          qid: p.id,
+          isFavorite: p.starred,
+          locked: p.locked,
+          state: this.parseProblemState(p.state),
+          name: p.name,
+          difficulty: p.level,
+          passRate: p.percent,
+          companies: p.companies || [],
+          tags: treeDataService.getTagsData(p.fid),
+          scoreData: AllScoreDataOnline.get(p.fid) || AllScoreData.get(p.fid),
+          isSearchResult: false,
+          input: "",
+          rootNodeSortId: RootNodeSort.ZERO,
+          todayData: undefined,
         });
-
-        if (!selectedItem) {
-            return;
-        }
-
-        leetCodeConfig.update("defaultLanguage", selectedItem.label, true /* Global */);
-        window.showInformationMessage(`设置默认语言 ${selectedItem.label} 成功`);
+      }
+      return problems.reverse();
+    } catch (error) {
+      await promptForOpenOutputChannel("获取题目失败. 请查看控制台信息~", DialogType.error);
+      return [];
     }
+  }
 
-
-    public isSubFolder(from: string, to: string): boolean {
-        const relative: string = path.relative(from, to);
-        if (relative === "") {
-            return true;
-        }
-        return !relative.startsWith("..") && !path.isAbsolute(relative);
-    }
-
-    public async determineLeetCodeFolder(): Promise {
-        let result: string;
-        const picks: Array> = [];
-        picks.push(
-            {
-                label: `Default location`,
-                detail: `${path.join(os.homedir(), ".leetcode")}`,
-                value: `${path.join(os.homedir(), ".leetcode")}`,
-            },
-            {
-                label: "$(file-directory) Browse...",
-                value: ":browse",
-            },
-        );
-        const choice: IQuickItemEx | undefined = await vscode.window.showQuickPick(
-            picks,
-            { placeHolder: "Select where you would like to save your LeetCode files" },
-        );
-        if (!choice) {
-            result = "";
-        } else if (choice.value === ":browse") {
-            const directory: vscode.Uri[] | undefined = await this.showDirectorySelectDialog();
-            if (!directory || directory.length < 1) {
-                result = "";
-            } else {
-                result = directory[0].fsPath;
-            }
-        } else {
-            result = choice.value;
-        }
-
-        getVsCodeConfig().update("workspaceFolder", result, vscode.ConfigurationTarget.Global);
-
-        return result;
+  public parseProblemState(stateOutput: string): ProblemState {
+    if (!stateOutput) {
+      return ProblemState.Unknown;
     }
-
-    public async showDirectorySelectDialog(fsPath?: string): Promise {
-        const defaultUri: vscode.Uri | undefined = this.getBelongingWorkspaceFolderUri(fsPath);
-        const options: vscode.OpenDialogOptions = {
-            defaultUri,
-            canSelectFiles: false,
-            canSelectFolders: true,
-            canSelectMany: false,
-            openLabel: "Select",
-        };
-        return await vscode.window.showOpenDialog(options);
+    switch (stateOutput.trim()) {
+      case "v":
+      case "✔":
+      case "√":
+      case "ac":
+        return ProblemState.AC;
+      case "X":
+      case "✘":
+      case "×":
+      case "notac":
+        return ProblemState.NotAC;
+      default:
+        return ProblemState.Unknown;
     }
-
-    public getBelongingWorkspaceFolderUri(fsPath: string | undefined): vscode.Uri | undefined {
-        let defaultUri: vscode.Uri | undefined;
-        if (fsPath) {
-            const workspaceFolder: vscode.WorkspaceFolder | undefined = vscode.workspace.getWorkspaceFolder(vscode.Uri.file(fsPath));
-            if (workspaceFolder) {
-                defaultUri = workspaceFolder.uri;
-            }
-        }
-        return defaultUri;
+  }
+
+  public async switchDefaultLanguage(): Promise {
+    const leetCodeConfig: WorkspaceConfiguration = workspace.getConfiguration("leetcode-problem-rating");
+    const defaultLanguage: string | undefined = leetCodeConfig.get("defaultLanguage");
+    const languageItems: QuickPickItem[] = [];
+    for (const language of languages) {
+      languageItems.push({
+        label: language,
+        description: defaultLanguage === language ? "Currently used" : undefined,
+      });
+    }
+    // Put the default language at the top of the list
+    languageItems.sort((a: QuickPickItem, b: QuickPickItem) => {
+      if (a.description) {
+        return Number.MIN_SAFE_INTEGER;
+      } else if (b.description) {
+        return Number.MAX_SAFE_INTEGER;
+      }
+      return a.label.localeCompare(b.label);
+    });
+
+    const selectedItem: QuickPickItem | undefined = await window.showQuickPick(languageItems, {
+      placeHolder: "请设置默认语言",
+      ignoreFocusOut: true,
+    });
+
+    if (!selectedItem) {
+      return;
     }
 
+    leetCodeConfig.update("defaultLanguage", selectedItem.label, true /* Global */);
+    window.showInformationMessage(`设置默认语言 ${selectedItem.label} 成功`);
+  }
 
-    public async searchProblem(): Promise {
-        if (!statusBarService.getUser()) {
-            promptForSignIn();
-            return;
-        }
-
-        const picks: Array> = [];
-        picks.push(
-            {
-                label: `题目id查询`,
-                detail: `通过题目id查询`,
-                value: `byid`,
-            },
-            {
-                label: `分数范围查询`,
-                detail: `例如 1500-1600`,
-                value: `range`,
-            },
-            {
-                label: `周赛期数查询`,
-                detail: `周赛期数查询`,
-                value: `contest`,
-            },
-            {
-                label: `测试api`,
-                detail: `测试api`,
-                value: `testapi`,
-            }
-            // ,
-            // {
-            //     label: `每日一题`,
-            //     detail: `每日一题`,
-            //     value: `today`,
-            // },
-            // {
-            //     label: `查询自己竞赛信息`,
-            //     detail: `查询自己竞赛信息`,
-            //     value: `userContest`,
-            // }
-        );
-        const choice: IQuickItemEx | undefined = await vscode.window.showQuickPick(
-            picks,
-            { title: "选择查询选项" },
-        );
-        if (!choice) {
-            return;
-        }
-        if (choice.value == "byid") {
-            await this.searchProblemByID();
-        } else if (choice.value == "range") {
-            await this.searchScoreRange();
-        } else if (choice.value == "contest") {
-            await this.searchContest();
-        } else if (choice.value == "today") {
-            await this.searchToday();
-        } else if (choice.value == "userContest") {
-            await this.searchUserContest();
-        } else if (choice.value == "testapi") {
-            await this.testapi();
-        }
+  public isSubFolder(from: string, to: string): boolean {
+    const relative: string = path.relative(from, to);
+    if (relative === "") {
+      return true;
+    }
+    return !relative.startsWith("..") && !path.isAbsolute(relative);
+  }
+
+  public async determineLeetCodeFolder(): Promise {
+    let result: string;
+    const picks: Array> = [];
+    picks.push(
+      {
+        label: `Default location`,
+        detail: `${path.join(os.homedir(), ".leetcode")}`,
+        value: `${path.join(os.homedir(), ".leetcode")}`,
+      },
+      {
+        label: "$(file-directory) Browse...",
+        value: ":browse",
+      }
+    );
+    const choice: IQuickItemEx | undefined = await vscode.window.showQuickPick(picks, {
+      placeHolder: "Select where you would like to save your LeetCode files",
+    });
+    if (!choice) {
+      result = "";
+    } else if (choice.value === ":browse") {
+      const directory: vscode.Uri[] | undefined = await this.showDirectorySelectDialog();
+      if (!directory || directory.length < 1) {
+        result = "";
+      } else {
+        result = directory[0].fsPath;
+      }
+    } else {
+      result = choice.value;
+    }
 
+    getVsCodeConfig().update("workspaceFolder", result, vscode.ConfigurationTarget.Global);
+
+    return result;
+  }
+
+  public async showDirectorySelectDialog(fsPath?: string): Promise {
+    const defaultUri: vscode.Uri | undefined = this.getBelongingWorkspaceFolderUri(fsPath);
+    const options: vscode.OpenDialogOptions = {
+      defaultUri,
+      canSelectFiles: false,
+      canSelectFolders: true,
+      canSelectMany: false,
+      openLabel: "Select",
+    };
+    return await vscode.window.showOpenDialog(options);
+  }
+
+  public getBelongingWorkspaceFolderUri(fsPath: string | undefined): vscode.Uri | undefined {
+    let defaultUri: vscode.Uri | undefined;
+    if (fsPath) {
+      const workspaceFolder: vscode.WorkspaceFolder | undefined = vscode.workspace.getWorkspaceFolder(
+        vscode.Uri.file(fsPath)
+      );
+      if (workspaceFolder) {
+        defaultUri = workspaceFolder.uri;
+      }
     }
+    return defaultUri;
+  }
 
-    public async showSolution(input: NodeModel | vscode.Uri): Promise {
-        let problemInput: string | undefined;
-        if (input instanceof NodeModel) { // Triggerred from explorer
-            problemInput = input.qid;
-        } else if (input instanceof vscode.Uri) { // Triggerred from Code Lens/context menu
-            if (systemUtils.useVscodeNode()) {
-                problemInput = `${input.fsPath}`;
-            } else {
-                problemInput = `"${input.fsPath}"`;
-                if (systemUtils.useWsl()) {
-                    problemInput = await systemUtils.toWslPath(input.fsPath);
-                }
-            }
-        } else if (!input) { // Triggerred from command
-            problemInput = await this.getActiveFilePath();
-        }
+  public async searchProblem(): Promise {
+    if (!statusBarService.getUser()) {
+      promptForSignIn();
+      return;
+    }
 
-        if (!problemInput) {
-            vscode.window.showErrorMessage("Invalid input to fetch the solution data.");
-            return;
-        }
+    const picks: Array> = [];
+    picks.push(
+      {
+        label: `题目id查询`,
+        detail: `通过题目id查询`,
+        value: `byid`,
+      },
+      {
+        label: `分数范围查询`,
+        detail: `例如 1500-1600`,
+        value: `range`,
+      },
+      {
+        label: `周赛期数查询`,
+        detail: `周赛期数查询`,
+        value: `contest`,
+      },
+      {
+        label: `测试api`,
+        detail: `测试api`,
+        value: `testapi`,
+      }
+      // ,
+      // {
+      //     label: `每日一题`,
+      //     detail: `每日一题`,
+      //     value: `today`,
+      // },
+      // {
+      //     label: `查询自己竞赛信息`,
+      //     detail: `查询自己竞赛信息`,
+      //     value: `userContest`,
+      // }
+    );
+    const choice: IQuickItemEx | undefined = await vscode.window.showQuickPick(picks, {
+      title: "选择查询选项",
+    });
+    if (!choice) {
+      return;
+    }
+    if (choice.value == "byid") {
+      await this.searchProblemByID();
+    } else if (choice.value == "range") {
+      await this.searchScoreRange();
+    } else if (choice.value == "contest") {
+      await this.searchContest();
+    } else if (choice.value == "today") {
+      await this.searchToday();
+    } else if (choice.value == "userContest") {
+      await this.searchUserContest();
+    } else if (choice.value == "testapi") {
+      await this.testapi();
+    }
+  }
+
+  public async showSolution(input: NodeModel | vscode.Uri): Promise {
+    let problemInput: string | undefined;
+    if (input instanceof NodeModel) {
+      // Triggerred from explorer
+      problemInput = input.qid;
+    } else if (input instanceof vscode.Uri) {
+      // Triggerred from Code Lens/context menu
+      if (systemUtils.useVscodeNode()) {
+        problemInput = `${input.fsPath}`;
+      } else {
+        problemInput = `"${input.fsPath}"`;
+        if (systemUtils.useWsl()) {
+          problemInput = await systemUtils.toWslPath(input.fsPath);
+        }
+      }
+    } else if (!input) {
+      // Triggerred from command
+      problemInput = await this.getActiveFilePath();
+    }
 
-        const language: string | undefined = await this.fetchProblemLanguage();
-        if (!language) {
-            return;
-        }
-        try {
-            const needTranslation: boolean = isUseEndpointTranslation();
-            const solution: string = await executeService.showSolution(problemInput, language, needTranslation);
-            solutionService.show(unescapeJS(solution));
-        } catch (error) {
-            logOutput.appendLine(error.toString());
-            await promptForOpenOutputChannel("Failed to fetch the top voted solution. 请查看控制台信息~", DialogType.error);
-        }
+    if (!problemInput) {
+      vscode.window.showErrorMessage("Invalid input to fetch the solution data.");
+      return;
     }
 
+    const language: string | undefined = await this.fetchProblemLanguage();
+    if (!language) {
+      return;
+    }
+    try {
+      const needTranslation: boolean = isUseEndpointTranslation();
+      const solution: string = await executeService.showSolution(problemInput, language, needTranslation);
+      solutionService.show(unescapeJS(solution));
+    } catch (error) {
+      logOutput.appendLine(error.toString());
+      await promptForOpenOutputChannel("Failed to fetch the top voted solution. 请查看控制台信息~", DialogType.error);
+    }
+  }
 
+  public async testapi(): Promise {
+    if (!statusBarService.getUser()) {
+      promptForSignIn();
+      return;
+    }
+    try {
+      const twoFactor: string | undefined = await vscode.window.showInputBox({
+        prompt: "测试数据",
+        ignoreFocusOut: true,
+        validateInput: (s: string): string | undefined => (s && s.trim() ? undefined : "The input must not be empty"),
+      });
+
+      // vscode.window.showErrorMessage(twoFactor || "输入错误");
+      const solution: string = await executeService.getTestApi(twoFactor || "");
+      const query_result = JSON.parse(solution);
+      console.log(query_result);
+    } catch (error) {
+      logOutput.appendLine(error.toString());
+      await promptForOpenOutputChannel("Failed to fetch today question. 请查看控制台信息~", DialogType.error);
+    }
+  }
 
-    public async testapi(): Promise {
-        if (!statusBarService.getUser()) {
-            promptForSignIn();
-            return;
-        }
-        try {
-            const twoFactor: string | undefined = await vscode.window.showInputBox({
-                prompt: "测试数据",
-                ignoreFocusOut: true,
-                validateInput: (s: string): string | undefined => s && s.trim() ? undefined : "The input must not be empty",
-            });
-
-            // vscode.window.showErrorMessage(twoFactor || "输入错误");
-            const solution: string = await executeService.getTestApi(twoFactor || "");
-            const query_result = JSON.parse(solution);
-            console.log(query_result);
-        } catch (error) {
-            logOutput.appendLine(error.toString());
-            await promptForOpenOutputChannel("Failed to fetch today question. 请查看控制台信息~", DialogType.error);
-        }
+  public async searchProblemByID(): Promise {
+    if (!statusBarService.getUser()) {
+      promptForSignIn();
+      return;
     }
+    const choice: IQuickItemEx | undefined = await vscode.window.showQuickPick(
+      this.parseProblemsToPicks(this.listProblems()),
+      {
+        matchOnDetail: true,
+        matchOnDescription: true,
+        placeHolder: "Select one problem",
+      }
+    );
+    if (!choice) {
+      return;
+    }
+    await this.showProblemInternal(choice.value);
+  }
 
+  public async showProblem(node?: NodeModel): Promise {
+    if (!node) {
+      return;
+    }
+    await this.showProblemInternal(node);
+  }
+
+  public async pickOne(): Promise {
+    const problems: IProblem[] = await this.listProblems();
+    let randomProblem: IProblem;
+
+    const user_score = statusBarService.getUserContestScore();
+    if (user_score > 0) {
+      let min_score: number = getPickOneByRankRangeMin();
+      let max_score: number = getPickOneByRankRangeMax();
+      let temp_problems: IProblem[] = [];
+      const need_min = user_score + min_score;
+      const need_max = user_score + max_score;
+      problems.forEach((element) => {
+        if (element.scoreData?.Rating) {
+          if (element.scoreData.Rating >= need_min && element.scoreData.Rating <= need_max) {
+            temp_problems.push(element);
+          }
+        }
+      });
+      randomProblem = temp_problems[Math.floor(Math.random() * temp_problems.length)];
+    } else {
+      randomProblem = problems[Math.floor(Math.random() * problems.length)];
+    }
+    if (randomProblem) {
+      await this.showProblemInternal(randomProblem);
+    }
+  }
 
-    public async searchProblemByID(): Promise {
-        if (!statusBarService.getUser()) {
-            promptForSignIn();
-            return;
-        }
-        const choice: IQuickItemEx | undefined = await vscode.window.showQuickPick(
-            this.parseProblemsToPicks(this.listProblems()),
-            {
-                matchOnDetail: true,
-                matchOnDescription: true,
-                placeHolder: "Select one problem",
-            },
+  public async fetchProblemLanguage(): Promise {
+    const leetCodeConfig: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("leetcode-problem-rating");
+    let defaultLanguage: string | undefined = leetCodeConfig.get("defaultLanguage");
+    if (defaultLanguage && languages.indexOf(defaultLanguage) < 0) {
+      defaultLanguage = undefined;
+    }
+    const language: string | undefined =
+      defaultLanguage ||
+      (await vscode.window.showQuickPick(languages, {
+        placeHolder: "Select the language you want to use",
+        ignoreFocusOut: true,
+      }));
+    // fire-and-forget default language query
+    (async (): Promise => {
+      if (language && !defaultLanguage && leetCodeConfig.get("hint.setDefaultLanguage")) {
+        const choice: vscode.MessageItem | undefined = await vscode.window.showInformationMessage(
+          `Would you like to set '${language}' as your default language?`,
+          DialogOptions.yes,
+          DialogOptions.no,
+          DialogOptions.never
         );
-        if (!choice) {
-            return;
-        }
-        await this.showProblemInternal(choice.value);
+        if (choice === DialogOptions.yes) {
+          leetCodeConfig.update("defaultLanguage", language, true /* UserSetting */);
+        } else if (choice === DialogOptions.never) {
+          leetCodeConfig.update("hint.setDefaultLanguage", false, true /* UserSetting */);
+        }
+      }
+    })();
+    return language;
+  }
+
+  public async selectWorkspaceFolder(): Promise {
+    let workspaceFolderSetting: string = getWorkspaceFolder();
+    if (workspaceFolderSetting.trim() === "") {
+      workspaceFolderSetting = await this.determineLeetCodeFolder();
+      if (workspaceFolderSetting === "") {
+        // User cancelled
+        return workspaceFolderSetting;
+      }
     }
-
-    public async showProblem(node?: NodeModel): Promise {
-        if (!node) {
-            return;
-        }
-        await this.showProblemInternal(node);
+    let needAsk: boolean = true;
+    await fse.ensureDir(workspaceFolderSetting);
+    for (const folder of vscode.workspace.workspaceFolders || []) {
+      if (this.isSubFolder(folder.uri.fsPath, workspaceFolderSetting)) {
+        needAsk = false;
+      }
     }
 
-
-    public async pickOne(): Promise {
-        const problems: IProblem[] = await this.listProblems();
-        let randomProblem: IProblem;
-
-        const user_score = statusBarService.getUserContestScore();
-        if (user_score > 0) {
-
-            let min_score: number = getPickOneByRankRangeMin();
-            let max_score: number = getPickOneByRankRangeMax();
-            let temp_problems: IProblem[] = [];
-            const need_min = user_score + min_score;
-            const need_max = user_score + max_score;
-            problems.forEach(element => {
-                if (element.scoreData?.Rating) {
-                    if (element.scoreData.Rating >= need_min && element.scoreData.Rating <= need_max) {
-                        temp_problems.push(element);
-                    }
-                }
-            });
-            randomProblem = temp_problems[Math.floor(Math.random() * temp_problems.length)];
-
-        } else {
-            randomProblem = problems[Math.floor(Math.random() * problems.length)];
-        }
-        if (randomProblem) {
-            await this.showProblemInternal(randomProblem);
-        }
+    if (needAsk) {
+      const choice: string | undefined = await vscode.window.showQuickPick(
+        [
+          OpenOption.justOpenFile,
+          OpenOption.openInCurrentWindow,
+          OpenOption.openInNewWindow,
+          OpenOption.addToWorkspace,
+        ],
+        {
+          placeHolder: "The LeetCode workspace folder is not opened in VS Code, would you like to open it?",
+        }
+      );
+
+      // Todo: generate file first
+      switch (choice) {
+        case OpenOption.justOpenFile:
+          return workspaceFolderSetting;
+        case OpenOption.openInCurrentWindow:
+          await vscode.commands.executeCommand("vscode.openFolder", vscode.Uri.file(workspaceFolderSetting), false);
+          return "";
+        case OpenOption.openInNewWindow:
+          await vscode.commands.executeCommand("vscode.openFolder", vscode.Uri.file(workspaceFolderSetting), true);
+          return "";
+        case OpenOption.addToWorkspace:
+          vscode.workspace.updateWorkspaceFolders(vscode.workspace.workspaceFolders?.length ?? 0, 0, {
+            uri: vscode.Uri.file(workspaceFolderSetting),
+          });
+          break;
+        default:
+          return "";
+      }
     }
 
-    public async fetchProblemLanguage(): Promise {
-        const leetCodeConfig: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("leetcode-problem-rating");
-        let defaultLanguage: string | undefined = leetCodeConfig.get("defaultLanguage");
-        if (defaultLanguage && languages.indexOf(defaultLanguage) < 0) {
-            defaultLanguage = undefined;
-        }
-        const language: string | undefined = defaultLanguage || await vscode.window.showQuickPick(languages, { placeHolder: "Select the language you want to use", ignoreFocusOut: true });
-        // fire-and-forget default language query
-        (async (): Promise => {
-            if (language && !defaultLanguage && leetCodeConfig.get("hint.setDefaultLanguage")) {
-                const choice: vscode.MessageItem | undefined = await vscode.window.showInformationMessage(
-                    `Would you like to set '${language}' as your default language?`,
-                    DialogOptions.yes,
-                    DialogOptions.no,
-                    DialogOptions.never,
-                );
-                if (choice === DialogOptions.yes) {
-                    leetCodeConfig.update("defaultLanguage", language, true /* UserSetting */);
-                } else if (choice === DialogOptions.never) {
-                    leetCodeConfig.update("hint.setDefaultLanguage", false, true /* UserSetting */);
-                }
-            }
-        })();
-        return language;
+    return systemUtils.useWsl() ? systemUtils.toWslPath(workspaceFolderSetting) : workspaceFolderSetting;
+  }
+
+  public async showProblemInternal(node: IProblem): Promise {
+    try {
+      const language: string | undefined = await this.fetchProblemLanguage();
+      if (!language) {
+        return;
+      }
+
+      const leetCodeConfig: vscode.WorkspaceConfiguration =
+        vscode.workspace.getConfiguration("leetcode-problem-rating");
+      const workspaceFolder: string = await this.selectWorkspaceFolder();
+      if (!workspaceFolder) {
+        return;
+      }
+
+      const fileFolder: string = leetCodeConfig
+        .get(`filePath.${language}.folder`, leetCodeConfig.get(`filePath.default.folder`, ""))
+        .trim();
+      const fileName: string = leetCodeConfig
+        .get(
+          `filePath.${language}.filename`,
+          leetCodeConfig.get(`filePath.default.filename`) || genFileName(node, language)
+        )
+        .trim();
+
+      let finalPath: string = path.join(workspaceFolder, fileFolder, fileName);
+
+      if (finalPath) {
+        finalPath = await this.resolveRelativePath(finalPath, node, language);
+        if (!finalPath) {
+          logOutput.appendLine("Showing problem canceled by user.");
+          return;
+        }
+      }
+
+      finalPath = systemUtils.useWsl() ? await systemUtils.toWinPath(finalPath) : finalPath;
+
+      const descriptionConfig: IDescriptionConfiguration = getDescriptionConfiguration();
+      const needTranslation: boolean = isUseEndpointTranslation();
+
+      await executeService.showProblem(node, language, finalPath, descriptionConfig.showInComment, needTranslation);
+      const promises: any[] = [
+        vscode.window.showTextDocument(vscode.Uri.file(finalPath), {
+          preview: false,
+          viewColumn: vscode.ViewColumn.One,
+        }),
+        promptHintMessage(
+          "hint.commentDescription",
+          'You can config how to show the problem description through "leetcode-problem-rating.showDescription".',
+          "Open settings",
+          (): Promise => openSettingsEditor("leetcode-problem-rating.showDescription")
+        ),
+      ];
+      if (descriptionConfig.showInWebview) {
+        promises.push(this.showDescriptionView(node));
+      }
+
+      await Promise.all(promises);
+    } catch (error) {
+      await promptForOpenOutputChannel(`${error} 请查看控制台信息~`, DialogType.error);
     }
-
-    public async selectWorkspaceFolder(): Promise {
-        let workspaceFolderSetting: string = getWorkspaceFolder();
-        if (workspaceFolderSetting.trim() === "") {
-            workspaceFolderSetting = await this.determineLeetCodeFolder();
-            if (workspaceFolderSetting === "") {
-                // User cancelled
-                return workspaceFolderSetting;
-            }
-        }
-        let needAsk: boolean = true;
-        await fse.ensureDir(workspaceFolderSetting);
-        for (const folder of vscode.workspace.workspaceFolders || []) {
-            if (this.isSubFolder(folder.uri.fsPath, workspaceFolderSetting)) {
-                needAsk = false;
-            }
-        }
-
-        if (needAsk) {
-            const choice: string | undefined = await vscode.window.showQuickPick(
-                [
-                    OpenOption.justOpenFile,
-                    OpenOption.openInCurrentWindow,
-                    OpenOption.openInNewWindow,
-                    OpenOption.addToWorkspace,
-                ],
-                { placeHolder: "The LeetCode workspace folder is not opened in VS Code, would you like to open it?" },
-            );
-
-            // Todo: generate file first
-            switch (choice) {
-                case OpenOption.justOpenFile:
-                    return workspaceFolderSetting;
-                case OpenOption.openInCurrentWindow:
-                    await vscode.commands.executeCommand("vscode.openFolder", vscode.Uri.file(workspaceFolderSetting), false);
-                    return "";
-                case OpenOption.openInNewWindow:
-                    await vscode.commands.executeCommand("vscode.openFolder", vscode.Uri.file(workspaceFolderSetting), true);
-                    return "";
-                case OpenOption.addToWorkspace:
-                    vscode.workspace.updateWorkspaceFolders(vscode.workspace.workspaceFolders?.length ?? 0, 0, { uri: vscode.Uri.file(workspaceFolderSetting) });
-                    break;
-                default:
-                    return "";
-            }
-        }
-
-        return systemUtils.useWsl() ? systemUtils.toWslPath(workspaceFolderSetting) : workspaceFolderSetting;
+  }
+
+  public async showDescriptionView(node: IProblem): Promise {
+    return this.previewProblem(node, enableSideMode());
+  }
+
+  public async previewProblem(input: IProblem | Uri, isSideMode: boolean = false): Promise {
+    let node: IProblem;
+    if (input instanceof Uri) {
+      const activeFilePath: string = input.fsPath;
+      const id: string = await getNodeIdFromFile(activeFilePath);
+      if (!id) {
+        window.showErrorMessage(`Failed to resolve the problem id from file: ${activeFilePath}.`);
+        return;
+      }
+      const cachedNode: IProblem | undefined = treeViewController.getNodeById(id);
+      if (!cachedNode) {
+        window.showErrorMessage(`Failed to resolve the problem with id: ${id}.`);
+        return;
+      }
+      node = cachedNode;
+      // Move the preview page aside if it's triggered from Code Lens
+      isSideMode = true;
+    } else {
+      node = input;
     }
-
-    public async showProblemInternal(node: IProblem): Promise {
-        try {
-            const language: string | undefined = await this.fetchProblemLanguage();
-            if (!language) {
-                return;
-            }
-
-            const leetCodeConfig: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("leetcode-problem-rating");
-            const workspaceFolder: string = await this.selectWorkspaceFolder();
-            if (!workspaceFolder) {
-                return;
-            }
-
-            const fileFolder: string = leetCodeConfig
-                .get(`filePath.${language}.folder`, leetCodeConfig.get(`filePath.default.folder`, ""))
-                .trim();
-            const fileName: string = leetCodeConfig
-                .get(
-                    `filePath.${language}.filename`,
-                    leetCodeConfig.get(`filePath.default.filename`) || genFileName(node, language),
-                )
-                .trim();
-
-            let finalPath: string = path.join(workspaceFolder, fileFolder, fileName);
-
-            if (finalPath) {
-                finalPath = await this.resolveRelativePath(finalPath, node, language);
-                if (!finalPath) {
-                    logOutput.appendLine("Showing problem canceled by user.");
-                    return;
-                }
-            }
-
-            finalPath = systemUtils.useWsl() ? await systemUtils.toWinPath(finalPath) : finalPath;
-
-            const descriptionConfig: IDescriptionConfiguration = getDescriptionConfiguration();
-            const needTranslation: boolean = isUseEndpointTranslation();
-
-            await executeService.showProblem(node, language, finalPath, descriptionConfig.showInComment, needTranslation);
-            const promises: any[] = [
-                vscode.window.showTextDocument(vscode.Uri.file(finalPath), { preview: false, viewColumn: vscode.ViewColumn.One }),
-                promptHintMessage(
-                    "hint.commentDescription",
-                    'You can config how to show the problem description through "leetcode-problem-rating.showDescription".',
-                    "Open settings",
-                    (): Promise => openSettingsEditor("leetcode-problem-rating.showDescription"),
-                ),
-            ];
-            if (descriptionConfig.showInWebview) {
-                promises.push(this.showDescriptionView(node));
-            }
-
-            await Promise.all(promises);
-        } catch (error) {
-            await promptForOpenOutputChannel(`${error} 请查看控制台信息~`, DialogType.error);
-        }
+    const needTranslation: boolean = isUseEndpointTranslation();
+    const descString: string = await executeService.getDescription(node.qid, needTranslation);
+    previewService.show(descString, node, isSideMode);
+  }
+
+  public async searchScoreRange(): Promise {
+    const twoFactor: string | undefined = await vscode.window.showInputBox({
+      prompt: "输入分数范围 低分-高分 例如: 1500-1600",
+      ignoreFocusOut: true,
+      validateInput: (s: string): string | undefined => (s && s.trim() ? undefined : "The input must not be empty"),
+    });
+
+    // vscode.window.showErrorMessage(twoFactor || "输入错误");
+    const tt = Object.assign({}, SearchNode, {
+      value: twoFactor,
+      type: SearchSetType.ScoreRange,
+      time: Math.floor(Date.now() / 1000),
+    });
+    treeViewController.insertSearchSet(tt);
+    await treeDataService.refresh();
+  }
+
+  public async searchContest(): Promise {
+    const twoFactor: string | undefined = await vscode.window.showInputBox({
+      prompt: "单期数 例如: 300 或者 输入期数范围 低期数-高期数 例如: 303-306",
+      ignoreFocusOut: true,
+      validateInput: (s: string): string | undefined => (s && s.trim() ? undefined : "The input must not be empty"),
+    });
+
+    // vscode.window.showErrorMessage(twoFactor || "输入错误");
+    const tt = Object.assign({}, SearchNode, {
+      value: twoFactor,
+      type: SearchSetType.Context,
+      time: Math.floor(Date.now() / 1000),
+    });
+    treeViewController.insertSearchSet(tt);
+    await treeDataService.refresh();
+  }
+
+  public async searchUserContest(): Promise {
+    if (!statusBarService.getUser()) {
+      promptForSignIn();
+      return;
     }
-
-    public async showDescriptionView(node: IProblem): Promise {
-        return this.previewProblem(node, enableSideMode());
+    try {
+      const needTranslation: boolean = isUseEndpointTranslation();
+      const solution: string = await executeService.getUserContest(needTranslation, statusBarService.getUser() || "");
+      const query_result = JSON.parse(solution);
+      const tt: userContestRanKingBase = Object.assign({}, userContestRankingObj, query_result.userContestRanking);
+      eventService.emit("searchUserContest", tt);
+    } catch (error) {
+      logOutput.appendLine(error.toString());
+      await promptForOpenOutputChannel("Failed to fetch today question. 请查看控制台信息~", DialogType.error);
     }
-
-    public async previewProblem(input: IProblem | Uri, isSideMode: boolean = false): Promise {
-        let node: IProblem;
-        if (input instanceof Uri) {
-            const activeFilePath: string = input.fsPath;
-            const id: string = await getNodeIdFromFile(activeFilePath);
-            if (!id) {
-                window.showErrorMessage(`Failed to resolve the problem id from file: ${activeFilePath}.`);
-                return;
-            }
-            const cachedNode: IProblem | undefined = treeViewController.getNodeById(id);
-            if (!cachedNode) {
-                window.showErrorMessage(`Failed to resolve the problem with id: ${id}.`);
-                return;
-            }
-            node = cachedNode;
-            // Move the preview page aside if it's triggered from Code Lens
-            isSideMode = true;
-        } else {
-            node = input;
-        }
-        const needTranslation: boolean = isUseEndpointTranslation();
-        const descString: string = await executeService.getDescription(node.qid, needTranslation);
-        previewService.show(descString, node, isSideMode);
+  }
+  public async searchToday(): Promise {
+    if (!statusBarService.getUser()) {
+      promptForSignIn();
+      return;
     }
-
-
-    public async searchScoreRange(): Promise {
-        const twoFactor: string | undefined = await vscode.window.showInputBox({
-            prompt: "输入分数范围 低分-高分 例如: 1500-1600",
-            ignoreFocusOut: true,
-            validateInput: (s: string): string | undefined => s && s.trim() ? undefined : "The input must not be empty",
-        });
-
-        // vscode.window.showErrorMessage(twoFactor || "输入错误");
+    try {
+      const needTranslation: boolean = isUseEndpointTranslation();
+      const solution: string = await executeService.getTodayQuestion(needTranslation);
+      const query_result = JSON.parse(solution);
+      // const titleSlug: string = query_result.titleSlug
+      // const questionId: string = query_result.questionId
+      const fid: string = query_result.fid;
+      if (fid) {
         const tt = Object.assign({}, SearchNode, {
-            value: twoFactor,
-            type: SearchSetType.ScoreRange,
-            time: Math.floor(Date.now() / 1000)
+          value: fid,
+          type: SearchSetType.Day,
+          time: Math.floor(Date.now() / 1000),
+          todayData: query_result,
         });
         treeViewController.insertSearchSet(tt);
         await treeDataService.refresh();
+      }
+    } catch (error) {
+      logOutput.appendLine(error.toString());
+      await promptForOpenOutputChannel("Failed to fetch today question. 请查看控制台信息~", DialogType.error);
     }
-
-    public async searchContest(): Promise {
-        const twoFactor: string | undefined = await vscode.window.showInputBox({
-            prompt: "单期数 例如: 300 或者 输入期数范围 低期数-高期数 例如: 303-306",
-            ignoreFocusOut: true,
-            validateInput: (s: string): string | undefined => s && s.trim() ? undefined : "The input must not be empty",
-        });
-
-        // vscode.window.showErrorMessage(twoFactor || "输入错误");
-        const tt = Object.assign({}, SearchNode, {
-            value: twoFactor,
-            type: SearchSetType.Context,
-            time: Math.floor(Date.now() / 1000)
-        });
-        treeViewController.insertSearchSet(tt);
-        await treeDataService.refresh();
+  }
+
+  public async parseProblemsToPicks(p: Promise): Promise>> {
+    return new Promise(async (resolve: (res: Array>) => void): Promise => {
+      const picks: Array> = (await p).map((problem: IProblem) =>
+        Object.assign(
+          {},
+          {
+            label: `${this.parseProblemDecorator(problem.state, problem.locked)}${problem.id}.${problem.name}`,
+            description: `QID:${problem.qid}`,
+            detail:
+              ((problem.scoreData?.score || "0") > "0" ? "score: " + problem.scoreData?.score + " , " : "") +
+              `AC rate: ${problem.passRate}, Difficulty: ${problem.difficulty}`,
+            value: problem,
+          }
+        )
+      );
+      resolve(picks);
+    });
+  }
+
+  public parseProblemDecorator(state: ProblemState, locked: boolean): string {
+    switch (state) {
+      case ProblemState.AC:
+        return "$(check) ";
+      case ProblemState.NotAC:
+        return "$(x) ";
+      default:
+        return locked ? "$(lock) " : "";
     }
+  }
 
-
-
-    public async searchUserContest(): Promise {
-        if (!statusBarService.getUser()) {
-            promptForSignIn();
-            return;
-        }
-        try {
-            const needTranslation: boolean = isUseEndpointTranslation();
-            const solution: string = await executeService.getUserContest(needTranslation, statusBarService.getUser() || "");
-            const query_result = JSON.parse(solution);
-            const tt: userContestRanKingBase = Object.assign({}, userContestRankingObj, query_result.userContestRanking);
-            eventService.emit("searchUserContest", tt);
-        } catch (error) {
-            logOutput.appendLine(error.toString());
-            await promptForOpenOutputChannel("Failed to fetch today question. 请查看控制台信息~", DialogType.error);
-        }
+  public async resolveRelativePath(relativePath: string, node: IProblem, selectedLanguage: string): Promise {
+    let tag: string = "";
+    if (/\$\{ tag \} /i.test(relativePath)) {
+      tag = (await this.resolveTagForProblem(node)) || "";
     }
-    public async searchToday(): Promise {
-        if (!statusBarService.getUser()) {
-            promptForSignIn();
-            return;
-        }
-        try {
-            const needTranslation: boolean = isUseEndpointTranslation();
-            const solution: string = await executeService.getTodayQuestion(needTranslation);
-            const query_result = JSON.parse(solution);
-            // const titleSlug: string = query_result.titleSlug
-            // const questionId: string = query_result.questionId
-            const fid: string = query_result.fid;
-            if (fid) {
-                const tt = Object.assign({}, SearchNode, {
-                    value: fid,
-                    type: SearchSetType.Day,
-                    time: Math.floor(Date.now() / 1000),
-                    todayData: query_result,
-                });
-                treeViewController.insertSearchSet(tt);
-                await treeDataService.refresh();
-            }
 
-        } catch (error) {
-            logOutput.appendLine(error.toString());
-            await promptForOpenOutputChannel("Failed to fetch today question. 请查看控制台信息~", DialogType.error);
-        }
+    let company: string = "";
+    if (/\$\{company\}/i.test(relativePath)) {
+      company = (await this.resolveCompanyForProblem(node)) || "";
     }
 
-
-
-
-    public async parseProblemsToPicks(p: Promise): Promise>> {
-        return new Promise(async (resolve: (res: Array>) => void): Promise => {
-            const picks: Array> = (await p).map((problem: IProblem) => Object.assign({}, {
-                label: `${this.parseProblemDecorator(problem.state, problem.locked)}${problem.id}.${problem.name}`,
-                description: `QID:${problem.qid}`,
-                detail: ((problem.scoreData?.score || "0") > "0" ? ("score: " + problem.scoreData?.score + " , ") : "") + `AC rate: ${problem.passRate}, Difficulty: ${problem.difficulty}`,
-                value: problem,
-            }));
-            resolve(picks);
-        });
+    let errorMsg: string;
+    return relativePath.replace(/\$\{(.*?)\}/g, (_substring: string, ...args: string[]) => {
+      const placeholder: string = args[0].toLowerCase().trim();
+      switch (placeholder) {
+        case "id":
+          return node.id;
+        case "name":
+          return node.name;
+        case "camelcasename":
+          return lodash.camelCase(node.name);
+        case "pascalcasename":
+          return lodash.upperFirst(lodash.camelCase(node.name));
+        case "kebabcasename":
+        case "kebab-case-name":
+          return lodash.kebabCase(node.name);
+        case "snakecasename":
+        case "snake_case_name":
+          return lodash.snakeCase(node.name);
+        case "ext":
+          return genFileExt(selectedLanguage);
+        case "language":
+          return selectedLanguage;
+        case "difficulty":
+          return node.difficulty.toLocaleLowerCase();
+        case "tag":
+          return tag;
+        case "company":
+          return company;
+        default:
+          errorMsg = `The config '${placeholder}' is not supported.`;
+          logOutput.appendLine(errorMsg);
+          throw new Error(errorMsg);
+      }
+    });
+  }
+
+  public async resolveTagForProblem(problem: IProblem): Promise {
+    if (problem.tags.length === 1) {
+      return problem.tags[0];
     }
-
-    public parseProblemDecorator(state: ProblemState, locked: boolean): string {
-        switch (state) {
-            case ProblemState.AC:
-                return "$(check) ";
-            case ProblemState.NotAC:
-                return "$(x) ";
-            default:
-                return locked ? "$(lock) " : "";
-        }
+    return await vscode.window.showQuickPick(problem.tags, {
+      matchOnDetail: true,
+      placeHolder: "Multiple tags available, please select one",
+      ignoreFocusOut: true,
+    });
+  }
+
+  public async resolveCompanyForProblem(problem: IProblem): Promise {
+    if (problem.companies.length === 1) {
+      return problem.companies[0];
     }
-
-    public async resolveRelativePath(relativePath: string, node: IProblem, selectedLanguage: string): Promise {
-        let tag: string = "";
-        if (/\$\{ tag \} /i.test(relativePath)) {
-            tag = (await this.resolveTagForProblem(node)) || "";
-        }
-
-        let company: string = "";
-        if (/\$\{company\}/i.test(relativePath)) {
-            company = (await this.resolveCompanyForProblem(node)) || "";
-        }
-
-        let errorMsg: string;
-        return relativePath.replace(/\$\{(.*?)\}/g, (_substring: string, ...args: string[]) => {
-            const placeholder: string = args[0].toLowerCase().trim();
-            switch (placeholder) {
-                case "id":
-                    return node.id;
-                case "name":
-                    return node.name;
-                case "camelcasename":
-                    return lodash.camelCase(node.name);
-                case "pascalcasename":
-                    return lodash.upperFirst(lodash.camelCase(node.name));
-                case "kebabcasename":
-                case "kebab-case-name":
-                    return lodash.kebabCase(node.name);
-                case "snakecasename":
-                case "snake_case_name":
-                    return lodash.snakeCase(node.name);
-                case "ext":
-                    return genFileExt(selectedLanguage);
-                case "language":
-                    return selectedLanguage;
-                case "difficulty":
-                    return node.difficulty.toLocaleLowerCase();
-                case "tag":
-                    return tag;
-                case "company":
-                    return company;
-                default:
-                    errorMsg = `The config '${placeholder}' is not supported.`;
-                    logOutput.appendLine(errorMsg);
-                    throw new Error(errorMsg);
+    return await vscode.window.showQuickPick(problem.companies, {
+      matchOnDetail: true,
+      placeHolder: "Multiple tags available, please select one",
+      ignoreFocusOut: true,
+    });
+  }
+
+  public insertSearchSet(tt: ISearchSet) {
+    this.searchSet.set(tt.value, tt);
+  }
+  public clearUserScore() {
+    this.waitUserContest = false;
+    this.waitTodayQuestion = false;
+    this.searchSet = new Map();
+  }
+
+  public checkSubmit(e: ISubmitEvent) {
+    if (e.sub_type == "submit" && e.accepted) {
+      const day_start = new Date(new Date().setHours(0, 0, 0, 0)).getTime() / 1000; //获取当天零点的时间
+      const day_end = new Date(new Date().setHours(0, 0, 0, 0) + 24 * 60 * 60 * 1000 - 1).getTime() / 1000; //获取当天23:59:59的时间
+      let need_get_today: boolean = false;
+      this.searchSet.forEach((element) => {
+        if (element.type == SearchSetType.Day) {
+          if (day_start <= element.time && element.time <= day_end) {
+            if (e.fid == element.value) {
+              need_get_today = true;
             }
-        });
-    }
-
-    public async resolveTagForProblem(problem: IProblem): Promise {
-        if (problem.tags.length === 1) {
-            return problem.tags[0];
+          }
         }
-        return await vscode.window.showQuickPick(
-            problem.tags,
-            {
-                matchOnDetail: true,
-                placeHolder: "Multiple tags available, please select one",
-                ignoreFocusOut: true,
-            },
-        );
+      });
+      if (need_get_today) {
+        this.searchToday();
+      }
     }
+  }
 
-    public async resolveCompanyForProblem(problem: IProblem): Promise {
-        if (problem.companies.length === 1) {
-            return problem.companies[0];
-        }
-        return await vscode.window.showQuickPick(problem.companies, {
-            matchOnDetail: true,
-            placeHolder: "Multiple tags available, please select one",
-            ignoreFocusOut: true,
-        });
+  public async refreshCheck(): Promise {
+    if (!statusBarService.getUser()) {
+      return;
     }
-
-
-    public insertSearchSet(tt: ISearchSet) {
-        this.searchSet.set(tt.value, tt);
-    }
-    public clearUserScore() {
-        this.waitUserContest = false;
-        this.waitTodayQuestion = false;
-        this.searchSet = new Map();
-    }
-
-    public checkSubmit(e: ISubmitEvent) {
-        if (e.sub_type == "submit" && e.accepted) {
-            const day_start = new Date(new Date().setHours(0, 0, 0, 0)).getTime() / 1000; //获取当天零点的时间
-            const day_end = new Date(new Date().setHours(0, 0, 0, 0) + 24 * 60 * 60 * 1000 - 1).getTime() / 1000; //获取当天23:59:59的时间
-            let need_get_today: boolean = false;
-            this.searchSet.forEach(element => {
-                if (element.type == SearchSetType.Day) {
-                    if (day_start <= element.time && element.time <= day_end) {
-                        if (e.fid == element.value) {
-                            need_get_today = true;
-                        }
-                    }
-                }
-            });
-            if (need_get_today) {
-                this.searchToday();
-            }
-        }
-    }
-
-    public async refreshCheck(): Promise {
-        if (!statusBarService.getUser()) {
-            return;
-        }
-        const day_start = new Date(new Date().setHours(0, 0, 0, 0)).getTime() / 1000; //获取当天零点的时间
-        const day_end = new Date(new Date().setHours(0, 0, 0, 0) + 24 * 60 * 60 * 1000 - 1).getTime() / 1000; //获取当天23:59:59的时间
-        let need_get_today: boolean = true;
-        this.searchSet.forEach(element => {
-            if (element.type == SearchSetType.Day) {
-                if (day_start <= element.time && element.time <= day_end) {
-                    need_get_today = false;
-                } else {
-                    this.waitTodayQuestion = false;
-                }
-            }
-        });
-        if (need_get_today && !this.waitTodayQuestion) {
-            this.waitTodayQuestion = true;
-            await this.searchToday();
-        }
-        let user_score = statusBarService.getUserContestScore();
-        if (!user_score && !this.waitUserContest) {
-            this.waitUserContest = true;
-            await this.searchUserContest();
+    const day_start = new Date(new Date().setHours(0, 0, 0, 0)).getTime() / 1000; //获取当天零点的时间
+    const day_end = new Date(new Date().setHours(0, 0, 0, 0) + 24 * 60 * 60 * 1000 - 1).getTime() / 1000; //获取当天23:59:59的时间
+    let need_get_today: boolean = true;
+    this.searchSet.forEach((element) => {
+      if (element.type == SearchSetType.Day) {
+        if (day_start <= element.time && element.time <= day_end) {
+          need_get_today = false;
+        } else {
+          this.waitTodayQuestion = false;
         }
+      }
+    });
+    if (need_get_today && !this.waitTodayQuestion) {
+      this.waitTodayQuestion = true;
+      await this.searchToday();
     }
-
-    public async refreshCache(): Promise {
-        const temp_searchSet: Map = this.searchSet;
-        const temp_waitTodayQuestion: boolean = this.waitTodayQuestion;
-        const temp_waitUserContest: boolean = this.waitUserContest;
-        this.dispose();
-        let user_score = statusBarService.getUserContestScore();
-        for (const problem of await this.listProblems()) {
-            this.explorerNodeMap.set(problem.id, new NodeModel(problem, true, user_score));
-            for (const company of problem.companies) {
-                this.companySet.add(company);
-            }
-            for (const tag of problem.tags) {
-                this.tagSet.add(tag);
-            }
-        }
-        this.searchSet = temp_searchSet;
-        this.waitTodayQuestion = temp_waitTodayQuestion;
-        this.waitUserContest = temp_waitUserContest;
-    }
-
-    public getRootNodes(): NodeModel[] {
-        let user_score = statusBarService.getUserContestScore();
-        const baseNode: NodeModel[] = [
-            new NodeModel(Object.assign({}, defaultProblem, {
-                id: Category.All,
-                name: Category.All,
-                rootNodeSortId: RootNodeSort.All,
-            }), false),
-            new NodeModel(Object.assign({}, defaultProblem, {
-                id: Category.Difficulty,
-                name: Category.Difficulty,
-                rootNodeSortId: RootNodeSort.Difficulty,
-            }), false),
-            new NodeModel(Object.assign({}, defaultProblem, {
-                id: Category.Tag,
-                name: Category.Tag,
-                rootNodeSortId: RootNodeSort.Tag,
-            }), false),
-            // new NodeModel(Object.assign({}, defaultProblem, {
-            //     id: Category.Company,
-            //     name: Category.Company,
-            //     rootNodeSortId: RootNodeSort.Company,
-            // }), false),
-            new NodeModel(Object.assign({}, defaultProblem, {
-                id: Category.Favorite,
-                name: Category.Favorite,
-                rootNodeSortId: RootNodeSort.Favorite,
-            }), false),
-            new NodeModel(Object.assign({}, defaultProblem, {
-                id: Category.Score,
-                name: Category.Score,
-                rootNodeSortId: RootNodeSort.Score,
-            }), false, user_score),
-            new NodeModel(Object.assign({}, defaultProblem, {
-                id: Category.Choice,
-                name: Category.Choice,
-                rootNodeSortId: RootNodeSort.Choice,
-            }), false),
-        ];
-        this.searchSet.forEach(element => {
-            if (element.type == SearchSetType.Day) {
-                const curDate = new Date(element.time * 1000);
-                baseNode.push(new NodeModel(Object.assign({}, defaultProblem, {
-                    id: element.type,
-                    name: "[" + (curDate.getFullYear()) + "-" + (curDate.getMonth() + 1) + "-" + (curDate.getDate()) + "]" + SearchSetTypeName[SearchSetType.Day],
-                    input: element.value,
-                    isSearchResult: true,
-                    rootNodeSortId: RootNodeSort[element.type],
-                    todayData: element.todayData
-                }), false));
-            } else {
-                baseNode.push(new NodeModel(Object.assign({}, defaultProblem, {
-                    id: element.type,
-                    name: SearchSetTypeName[element.type] + element.value,
-                    input: element.value,
-                    isSearchResult: true,
-                    rootNodeSortId: RootNodeSort[element.type],
-                }), false));
-            }
-        });
-        baseNode.sort(function (a: NodeModel, b: NodeModel): number {
-            if (a.rootNodeSortId < b.rootNodeSortId) {
-                return -1;
-            } else if (a.rootNodeSortId > b.rootNodeSortId) {
-                return 1;
-            }
-            return 0;
-        });
-        return baseNode;
-    }
-
-    public getScoreRangeNodes(rank_range: string): NodeModel[] {
-        const sorceNode: NodeModel[] = [];
-        const rank_r: Array = rank_range.split("-");
-        let rank_a = Number(rank_r[0]);
-        let rank_b = Number(rank_r[1]);
-        if (rank_a > 0 && rank_b > 0) {
-            if (rank_a > rank_b) {
-                const rank_c: number = rank_a;
-                rank_a = rank_b;
-                rank_b = rank_c;
-            }
-
-            this.explorerNodeMap.forEach(element => {
-                if (!this.canShow(element)) {
-                    return;
-                }
-                if (rank_a <= Number(element.score) && Number(element.score) <= rank_b) {
-                    sorceNode.push(element);
-                }
-            });
-        }
-        return this.applySortingStrategy(sorceNode);
+    let user_score = statusBarService.getUserContestScore();
+    if (!user_score && !this.waitUserContest) {
+      this.waitUserContest = true;
+      await this.searchUserContest();
     }
-
-    public canShow(element: NodeModel) {
-        if (isHideSolvedProblem() && element.state === ProblemState.AC) {
-            return false;
-        }
-        if (isHideScoreProblem(element, element.user_score)) {
-            return false;
-        }
-        return true;
-    }
-
-    public getContextNodes(rank_range: string): NodeModel[] {
-        const sorceNode: NodeModel[] = [];
-        const rank_r: Array = rank_range.split("-");
-        let rank_a = Number(rank_r[0]);
-        let rank_b = Number(rank_r[1]);
-        if (rank_a > 0) {
-            this.explorerNodeMap.forEach(element => {
-                if (!this.canShow(element)) {
-                    return;
-                }
-                const slu = element.ContestSlug;
-                const slu_arr: Array = slu.split("-");
-                const slu_id = Number(slu_arr[slu_arr.length - 1]);
-                if (rank_b > 0 && rank_a <= slu_id && slu_id <= rank_b) {
-                    sorceNode.push(element);
-                } else if (rank_a == slu_id) {
-                    sorceNode.push(element);
-                }
-            });
-        }
-        return this.applySortingStrategy(sorceNode);
-    }
-    public getDayNodes(element: NodeModel | undefined): NodeModel[] {
-        const rank_range: string = element?.input || "";
-        const sorceNode: NodeModel[] = [];
-        if (rank_range) {
-            this.explorerNodeMap.forEach(new_node => {
-                if (new_node.id == rank_range) {
-                    new_node.todayData = element?.todayData;
-                    sorceNode.push(new_node);
-                }
-            });
-        }
-        return this.applySortingStrategy(sorceNode);
+  }
+
+  public async refreshCache(): Promise {
+    const temp_searchSet: Map = this.searchSet;
+    const temp_waitTodayQuestion: boolean = this.waitTodayQuestion;
+    const temp_waitUserContest: boolean = this.waitUserContest;
+    this.dispose();
+    let user_score = statusBarService.getUserContestScore();
+    for (const problem of await this.listProblems()) {
+      this.explorerNodeMap.set(problem.id, new NodeModel(problem, true, user_score));
+      for (const company of problem.companies) {
+        this.companySet.add(company);
+      }
+      for (const tag of problem.tags) {
+        this.tagSet.add(tag);
+      }
     }
-
-    public getAllNodes(): NodeModel[] {
-        return this.applySortingStrategy(
-            Array.from(this.explorerNodeMap.values()).filter(p => this.canShow(p)),
+    this.searchSet = temp_searchSet;
+    this.waitTodayQuestion = temp_waitTodayQuestion;
+    this.waitUserContest = temp_waitUserContest;
+  }
+
+  public getRootNodes(): NodeModel[] {
+    let user_score = statusBarService.getUserContestScore();
+    const baseNode: NodeModel[] = [
+      new NodeModel(
+        Object.assign({}, defaultProblem, {
+          id: Category.All,
+          name: Category.All,
+          rootNodeSortId: RootNodeSort.All,
+        }),
+        false
+      ),
+      new NodeModel(
+        Object.assign({}, defaultProblem, {
+          id: Category.Difficulty,
+          name: Category.Difficulty,
+          rootNodeSortId: RootNodeSort.Difficulty,
+        }),
+        false
+      ),
+      new NodeModel(
+        Object.assign({}, defaultProblem, {
+          id: Category.Tag,
+          name: Category.Tag,
+          rootNodeSortId: RootNodeSort.Tag,
+        }),
+        false
+      ),
+      // new NodeModel(Object.assign({}, defaultProblem, {
+      //     id: Category.Company,
+      //     name: Category.Company,
+      //     rootNodeSortId: RootNodeSort.Company,
+      // }), false),
+      new NodeModel(
+        Object.assign({}, defaultProblem, {
+          id: Category.Favorite,
+          name: Category.Favorite,
+          rootNodeSortId: RootNodeSort.Favorite,
+        }),
+        false
+      ),
+      new NodeModel(
+        Object.assign({}, defaultProblem, {
+          id: Category.Score,
+          name: Category.Score,
+          rootNodeSortId: RootNodeSort.Score,
+        }),
+        false,
+        user_score
+      ),
+      new NodeModel(
+        Object.assign({}, defaultProblem, {
+          id: Category.Choice,
+          name: Category.Choice,
+          rootNodeSortId: RootNodeSort.Choice,
+        }),
+        false
+      ),
+    ];
+    this.searchSet.forEach((element) => {
+      if (element.type == SearchSetType.Day) {
+        const curDate = new Date(element.time * 1000);
+        baseNode.push(
+          new NodeModel(
+            Object.assign({}, defaultProblem, {
+              id: element.type,
+              name:
+                "[" +
+                curDate.getFullYear() +
+                "-" +
+                (curDate.getMonth() + 1) +
+                "-" +
+                curDate.getDate() +
+                "]" +
+                SearchSetTypeName[SearchSetType.Day],
+              input: element.value,
+              isSearchResult: true,
+              rootNodeSortId: RootNodeSort[element.type],
+              todayData: element.todayData,
+            }),
+            false
+          )
         );
+      } else {
+        baseNode.push(
+          new NodeModel(
+            Object.assign({}, defaultProblem, {
+              id: element.type,
+              name: SearchSetTypeName[element.type] + element.value,
+              input: element.value,
+              isSearchResult: true,
+              rootNodeSortId: RootNodeSort[element.type],
+            }),
+            false
+          )
+        );
+      }
+    });
+    baseNode.sort(function (a: NodeModel, b: NodeModel): number {
+      if (a.rootNodeSortId < b.rootNodeSortId) {
+        return -1;
+      } else if (a.rootNodeSortId > b.rootNodeSortId) {
+        return 1;
+      }
+      return 0;
+    });
+    return baseNode;
+  }
+
+  public getScoreRangeNodes(rank_range: string): NodeModel[] {
+    const sorceNode: NodeModel[] = [];
+    const rank_r: Array = rank_range.split("-");
+    let rank_a = Number(rank_r[0]);
+    let rank_b = Number(rank_r[1]);
+    if (rank_a > 0 && rank_b > 0) {
+      if (rank_a > rank_b) {
+        const rank_c: number = rank_a;
+        rank_a = rank_b;
+        rank_b = rank_c;
+      }
+
+      this.explorerNodeMap.forEach((element) => {
+        if (!this.canShow(element)) {
+          return;
+        }
+        if (rank_a <= Number(element.score) && Number(element.score) <= rank_b) {
+          sorceNode.push(element);
+        }
+      });
     }
+    return this.applySortingStrategy(sorceNode);
+  }
 
-    public getAllDifficultyNodes(): NodeModel[] {
-        const res: NodeModel[] = [];
+  public canShow(element: NodeModel) {
+    if (isHideSolvedProblem() && element.state === ProblemState.AC) {
+      return false;
+    }
+    if (isHideScoreProblem(element, element.user_score)) {
+      return false;
+    }
+    return true;
+  }
+
+  public getContextNodes(rank_range: string): NodeModel[] {
+    const sorceNode: NodeModel[] = [];
+    const rank_r: Array = rank_range.split("-");
+    let rank_a = Number(rank_r[0]);
+    let rank_b = Number(rank_r[1]);
+    if (rank_a > 0) {
+      this.explorerNodeMap.forEach((element) => {
+        if (!this.canShow(element)) {
+          return;
+        }
+        const slu = element.ContestSlug;
+        const slu_arr: Array = slu.split("-");
+        const slu_id = Number(slu_arr[slu_arr.length - 1]);
+        if (rank_b > 0 && rank_a <= slu_id && slu_id <= rank_b) {
+          sorceNode.push(element);
+        } else if (rank_a == slu_id) {
+          sorceNode.push(element);
+        }
+      });
+    }
+    return this.applySortingStrategy(sorceNode);
+  }
+  public getDayNodes(element: NodeModel | undefined): NodeModel[] {
+    const rank_range: string = element?.input || "";
+    const sorceNode: NodeModel[] = [];
+    if (rank_range) {
+      this.explorerNodeMap.forEach((new_node) => {
+        if (new_node.id == rank_range) {
+          new_node.todayData = element?.todayData;
+          sorceNode.push(new_node);
+        }
+      });
+    }
+    return this.applySortingStrategy(sorceNode);
+  }
+
+  public getAllNodes(): NodeModel[] {
+    return this.applySortingStrategy(Array.from(this.explorerNodeMap.values()).filter((p) => this.canShow(p)));
+  }
+
+  public getAllDifficultyNodes(): NodeModel[] {
+    const res: NodeModel[] = [];
+    res.push(
+      new NodeModel(
+        Object.assign({}, defaultProblem, {
+          id: `${Category.Difficulty}.Easy`,
+          name: "Easy",
+        }),
+        false
+      ),
+      new NodeModel(
+        Object.assign({}, defaultProblem, {
+          id: `${Category.Difficulty}.Medium`,
+          name: "Medium",
+        }),
+        false
+      ),
+      new NodeModel(
+        Object.assign({}, defaultProblem, {
+          id: `${Category.Difficulty}.Hard`,
+          name: "Hard",
+        }),
+        false
+      )
+    );
+    this.sortSubCategoryNodes(res, Category.Difficulty);
+    return res;
+  }
+
+  public getAllScoreNodes(user_score: number): NodeModel[] {
+    const res: NodeModel[] = [];
+    const score_array: Array = [
+      "3300",
+      "3200",
+      "3100",
+      "3000",
+      "2900",
+      "2800",
+      "2700",
+      "2600",
+      "2500",
+      "2400",
+      "2300",
+      "2200",
+      "2100",
+      "2000",
+      "1900",
+      "1800",
+      "1700",
+      "1600",
+      "1500",
+      "1400",
+      "1300",
+      "1200",
+      "1100",
+    ];
+    score_array.forEach((element) => {
+      const temp_num = Number(element);
+      const diff = Math.abs(temp_num - user_score);
+      if (diff <= 200) {
         res.push(
-            new NodeModel(Object.assign({}, defaultProblem, {
-                id: `${Category.Difficulty}.Easy`,
-                name: "Easy",
-            }), false),
-            new NodeModel(Object.assign({}, defaultProblem, {
-                id: `${Category.Difficulty}.Medium`,
-                name: "Medium",
-            }), false),
-            new NodeModel(Object.assign({}, defaultProblem, {
-                id: `${Category.Difficulty}.Hard`,
-                name: "Hard",
-            }), false),
+          new NodeModel(
+            Object.assign({}, defaultProblem, {
+              id: `${Category.Score}.${element}`,
+              name: `${element}`,
+            }),
+            false,
+            user_score
+          )
         );
-        this.sortSubCategoryNodes(res, Category.Difficulty);
-        return res;
-    }
-
-    public getAllScoreNodes(user_score: number): NodeModel[] {
-        const res: NodeModel[] = [];
-        const score_array: Array = ["3300", "3200", "3100", "3000", "2900", "2800", "2700", "2600", "2500", "2400", "2300", "2200", "2100", "2000", "1900", "1800", "1700", "1600", "1500", "1400", "1300", "1200", "1100"];
-        score_array.forEach(element => {
-            const temp_num = Number(element);
-            const diff = Math.abs(temp_num - user_score);
-            if (diff <= 200) {
-                res.push(new NodeModel(Object.assign({}, defaultProblem, {
-                    id: `${Category.Score}.${element}`,
-                    name: `${element}`,
-                }), false, user_score));
-            }
-        });
-
-        this.sortSubCategoryNodes(res, Category.Score);
-        return res;
+      }
+    });
+
+    this.sortSubCategoryNodes(res, Category.Score);
+    return res;
+  }
+
+  public getAllChoiceNodes(): NodeModel[] {
+    const res: NodeModel[] = [];
+
+    const all_choice = treeDataService.getChoiceData();
+    all_choice.forEach((element) => {
+      res.push(
+        new NodeModel(
+          Object.assign({}, defaultProblem, {
+            id: `${Category.Choice}.${element.id}`,
+            name: `${element.name}`,
+          }),
+          false
+        )
+      );
+    });
+    this.sortSubCategoryNodes(res, Category.Choice);
+    return res;
+  }
+
+  public getAllCompanyNodes(): NodeModel[] {
+    const res: NodeModel[] = [];
+    for (const company of this.companySet.values()) {
+      res.push(
+        new NodeModel(
+          Object.assign({}, defaultProblem, {
+            id: `${Category.Company}.${company}`,
+            name: lodash.startCase(company),
+          }),
+          false
+        )
+      );
     }
-
-    public getAllChoiceNodes(): NodeModel[] {
-        const res: NodeModel[] = [];
-
-        const all_choice = treeDataService.getChoiceData();
-        all_choice.forEach(element => {
-            res.push(new NodeModel(Object.assign({}, defaultProblem, {
-                id: `${Category.Choice}.${element.id}`,
-                name: `${element.name}`,
-            }), false));
-        });
-        this.sortSubCategoryNodes(res, Category.Choice);
-        return res;
+    this.sortSubCategoryNodes(res, Category.Company);
+    return res;
+  }
+
+  public getAllTagNodes(): NodeModel[] {
+    const res: NodeModel[] = [];
+    for (const tag of this.tagSet.values()) {
+      res.push(
+        new NodeModel(
+          Object.assign({}, defaultProblem, {
+            id: `${Category.Tag}.${tag}`,
+            name: lodash.startCase(tag),
+          }),
+          false
+        )
+      );
     }
-
-    public getAllCompanyNodes(): NodeModel[] {
-        const res: NodeModel[] = [];
-        for (const company of this.companySet.values()) {
-            res.push(new NodeModel(Object.assign({}, defaultProblem, {
-                id: `${Category.Company}.${company}`,
-                name: lodash.startCase(company),
-            }), false));
-        }
-        this.sortSubCategoryNodes(res, Category.Company);
-        return res;
+    this.sortSubCategoryNodes(res, Category.Tag);
+    return res;
+  }
+
+  public getNodeById(id: string): NodeModel | undefined {
+    return this.explorerNodeMap.get(id);
+  }
+
+  public getFavoriteNodes(): NodeModel[] {
+    const res: NodeModel[] = [];
+    for (const node of this.explorerNodeMap.values()) {
+      if (!this.canShow(node)) {
+        continue;
+      }
+      if (node.isFavorite) {
+        res.push(node);
+      }
     }
-
-    public getAllTagNodes(): NodeModel[] {
-        const res: NodeModel[] = [];
-        for (const tag of this.tagSet.values()) {
-            res.push(new NodeModel(Object.assign({}, defaultProblem, {
-                id: `${Category.Tag}.${tag}`,
-                name: lodash.startCase(tag),
-            }), false));
-        }
-        this.sortSubCategoryNodes(res, Category.Tag);
-        return res;
+    return this.applySortingStrategy(res);
+  }
+
+  public getChildrenNodesById(id: string): NodeModel[] {
+    // The sub-category node's id is named as {Category.SubName}
+    const metaInfo: string[] = id.split(".");
+    const res: NodeModel[] = [];
+
+    const choiceQuestionId: Map = new Map();
+    if (metaInfo[0] == Category.Choice) {
+      const all_choice = treeDataService.getChoiceData();
+      all_choice.forEach((element) => {
+        if (element.id == metaInfo[1]) {
+          element.questions.forEach((kk) => {
+            choiceQuestionId[kk] = true;
+          });
+          return;
+        }
+      });
     }
 
-    public getNodeById(id: string): NodeModel | undefined {
-        return this.explorerNodeMap.get(id);
-    }
-
-    public getFavoriteNodes(): NodeModel[] {
-        const res: NodeModel[] = [];
-        for (const node of this.explorerNodeMap.values()) {
-            if (!this.canShow(node)) {
-                continue;
-            }
-            if (node.isFavorite) {
-                res.push(node);
-            }
-        }
-        return this.applySortingStrategy(res);
-    }
-
-    public getChildrenNodesById(id: string): NodeModel[] {
-        // The sub-category node's id is named as {Category.SubName}
-        const metaInfo: string[] = id.split(".");
-        const res: NodeModel[] = [];
-
-        const choiceQuestionId: Map = new Map();
-        if (metaInfo[0] == Category.Choice) {
-            const all_choice = treeDataService.getChoiceData();
-            all_choice.forEach(element => {
-                if (element.id == metaInfo[1]) {
-                    element.questions.forEach(kk => {
-                        choiceQuestionId[kk] = true;
-                    });
-                    return;
-                }
-            });
-        }
-
-        for (const node of this.explorerNodeMap.values()) {
-            if (!this.canShow(node)) {
-                continue;
+    for (const node of this.explorerNodeMap.values()) {
+      if (!this.canShow(node)) {
+        continue;
+      }
+      switch (metaInfo[0]) {
+        case Category.Company:
+          if (node.companies.indexOf(metaInfo[1]) >= 0) {
+            res.push(node);
+          }
+          break;
+        case Category.Difficulty:
+          if (node.difficulty === metaInfo[1]) {
+            res.push(node);
+          }
+          break;
+        case Category.Tag:
+          if (node.tags.indexOf(metaInfo[1]) >= 0) {
+            res.push(node);
+          }
+          break;
+        case Category.Score:
+          if (node.score > "0") {
+            const check_rank = toNumber(metaInfo[1]);
+            const node_rank = toNumber(node.score);
+            if (check_rank <= node_rank && node_rank < check_rank + 100) {
+              res.push(node);
             }
-            switch (metaInfo[0]) {
-                case Category.Company:
-                    if (node.companies.indexOf(metaInfo[1]) >= 0) {
-                        res.push(node);
-                    }
-                    break;
-                case Category.Difficulty:
-                    if (node.difficulty === metaInfo[1]) {
-                        res.push(node);
-                    }
-                    break;
-                case Category.Tag:
-                    if (node.tags.indexOf(metaInfo[1]) >= 0) {
-                        res.push(node);
-                    }
-                    break;
-                case Category.Score:
-                    if (node.score > "0") {
-                        const check_rank = toNumber(metaInfo[1]);
-                        const node_rank = toNumber(node.score);
-                        if (check_rank <= node_rank && node_rank < check_rank + 100) {
-                            res.push(node);
-                        }
-                    }
-                    break;
-                case Category.Choice:
-                    if (choiceQuestionId[Number(node.qid)]) {
-                        res.push(node);
-                    }
+          }
+          break;
+        case Category.Choice:
+          if (choiceQuestionId[Number(node.qid)]) {
+            res.push(node);
+          }
+      }
+    }
+    return this.applySortingStrategy(res);
+  }
+
+  public dispose(): void {
+    this.explorerNodeMap.clear();
+    this.companySet.clear();
+    this.tagSet.clear();
+  }
+
+  private sortSubCategoryNodes(subCategoryNodes: NodeModel[], category: Category): void {
+    switch (category) {
+      case Category.Difficulty:
+        subCategoryNodes.sort((a: NodeModel, b: NodeModel): number => {
+          function getValue(input: NodeModel): number {
+            switch (input.name.toLowerCase()) {
+              case "easy":
+                return 1;
+              case "medium":
+                return 2;
+              case "hard":
+                return 3;
+              default:
+                return Number.MAX_SAFE_INTEGER;
             }
-        }
-        return this.applySortingStrategy(res);
-    }
-
-    public dispose(): void {
-        this.explorerNodeMap.clear();
-        this.companySet.clear();
-        this.tagSet.clear();
-    }
-
-    private sortSubCategoryNodes(subCategoryNodes: NodeModel[], category: Category): void {
-        switch (category) {
-            case Category.Difficulty:
-                subCategoryNodes.sort((a: NodeModel, b: NodeModel): number => {
-                    function getValue(input: NodeModel): number {
-                        switch (input.name.toLowerCase()) {
-                            case "easy":
-                                return 1;
-                            case "medium":
-                                return 2;
-                            case "hard":
-                                return 3;
-                            default:
-                                return Number.MAX_SAFE_INTEGER;
-                        }
-                    }
-                    return getValue(a) - getValue(b);
-                });
-                break;
-            case Category.Tag:
-            case Category.Company:
-                subCategoryNodes.sort((a: NodeModel, b: NodeModel): number => {
-                    if (a.name === "Unknown") {
-                        return 1;
-                    } else if (b.name === "Unknown") {
-                        return -1;
-                    } else {
-                        return Number(a.name > b.name) - Number(a.name < b.name);
-                    }
-                });
-                break;
-            default:
-                break;
-        }
+          }
+          return getValue(a) - getValue(b);
+        });
+        break;
+      case Category.Tag:
+      case Category.Company:
+        subCategoryNodes.sort((a: NodeModel, b: NodeModel): number => {
+          if (a.name === "Unknown") {
+            return 1;
+          } else if (b.name === "Unknown") {
+            return -1;
+          } else {
+            return Number(a.name > b.name) - Number(a.name < b.name);
+          }
+        });
+        break;
+      default:
+        break;
     }
-
-    private applySortingStrategy(nodes: NodeModel[]): NodeModel[] {
-        const strategy: SortingStrategy = getSortingStrategy();
-        switch (strategy) {
-            case SortingStrategy.AcceptanceRateAsc: return nodes.sort((x: NodeModel, y: NodeModel) => Number(x.acceptanceRate) - Number(y.acceptanceRate));
-            case SortingStrategy.AcceptanceRateDesc: return nodes.sort((x: NodeModel, y: NodeModel) => Number(y.acceptanceRate) - Number(x.acceptanceRate));
-            case SortingStrategy.ScoreAsc: return nodes.sort((x: NodeModel, y: NodeModel) => Number(x.score) - Number(y.score));
-            case SortingStrategy.ScoreDesc: return nodes.sort((x: NodeModel, y: NodeModel) => Number(y.score) - Number(x.score));
-            case SortingStrategy.IDDesc: return nodes.sort((x: NodeModel, y: NodeModel) => Number(y.id) - Number(x.id));
-            default: return nodes;
-        }
+  }
+
+  private applySortingStrategy(nodes: NodeModel[]): NodeModel[] {
+    const strategy: SortingStrategy = getSortingStrategy();
+    switch (strategy) {
+      case SortingStrategy.AcceptanceRateAsc:
+        return nodes.sort((x: NodeModel, y: NodeModel) => Number(x.acceptanceRate) - Number(y.acceptanceRate));
+      case SortingStrategy.AcceptanceRateDesc:
+        return nodes.sort((x: NodeModel, y: NodeModel) => Number(y.acceptanceRate) - Number(x.acceptanceRate));
+      case SortingStrategy.ScoreAsc:
+        return nodes.sort((x: NodeModel, y: NodeModel) => Number(x.score) - Number(y.score));
+      case SortingStrategy.ScoreDesc:
+        return nodes.sort((x: NodeModel, y: NodeModel) => Number(y.score) - Number(x.score));
+      case SortingStrategy.IDDesc:
+        return nodes.sort((x: NodeModel, y: NodeModel) => Number(y.id) - Number(x.id));
+      default:
+        return nodes;
     }
+  }
 }
 
 export const treeViewController: TreeViewController = new TreeViewController();
diff --git a/src/dao/choiceDao.ts b/src/dao/choiceDao.ts
index ec3bba4..178f2ad 100644
--- a/src/dao/choiceDao.ts
+++ b/src/dao/choiceDao.ts
@@ -8,2088 +8,266 @@
  */
 
 class ChoiceDao {
-
-    public getChoiceData() {
-        return this.choiceData;
-    }
-
-    private choiceData = [
-        {
-            "id": "shopee",
-            "name": "Shopee精选",
-            "questions": [
-                341,
-                1000447,
-                1000446,
-                1000445,
-                1000444,
-                1000443,
-                232,
-                871,
-                102,
-                101,
-                15,
-                460,
-                456,
-                448,
-                179,
-                432,
-                48,
-                37,
-                20,
-                146
-            ],
-
-        },
-        {
-            "id": "binary-search",
-            "name": "二分查找",
-            "questions": [
-                4,
-                1550,
-                540,
-                1056,
-                33,
-                34,
-                35,
-                1059,
-                1060,
-                1083,
-                2047,
-                69,
-                1605,
-                74,
-                1612,
-                1102,
-                1615,
-                81,
-                1621,
-                1122,
-                611,
-                1645,
-                1134,
-                1646,
-                1143,
-                633,
-                1149,
-                644,
-                1672,
-                1675,
-                1679,
-                658,
-                1684,
-                153,
-                154,
-                668,
-                1185,
-                162,
-                167,
-                1192,
-                1730,
-                718,
-                719,
-                1232,
-                209,
-                1753,
-                222,
-                1249,
-                1766,
-                745,
-                1771,
-                1262,
-                240,
-                1290,
-                270,
-                786,
-                275,
-                788,
-                278,
-                792,
-                794,
-                1307,
-                287,
-                802,
-                1831,
-                1832,
-                809,
-                300,
-                302,
-                1326,
-                1851,
-                1352,
-                853,
-                350,
-                1374,
-                352,
-                1886,
-                1891,
-                1384,
-                363,
-                367,
-                882,
-                374,
-                378,
-                894,
-                1918,
-                1408,
-                1413,
-                1929,
-                907,
-                912,
-                1946,
-                923,
-                1957,
-                1966,
-                947,
-                436,
-                1463,
-                441,
-                1468,
-                1984,
-                1476,
-                1486,
-                2000,
-                2006,
-                2018,
-                2027,
-                2036,
-                2045,
-                1023
-            ],
-
-        },
-        {
-            "id": "lcof",
-            "name": "剑指 Offer",
-            "questions": [
-                1000228,
-                1000229,
-                1000230,
-                1000231,
-                1000232,
-                1000233,
-                1000234,
-                1000235,
-                1000236,
-                1000237,
-                1000238,
-                1000239,
-                1000240,
-                1000241,
-                1000242,
-                1000243,
-                1000244,
-                1000245,
-                1000246,
-                1000247,
-                1000248,
-                1000249,
-                1000250,
-                1000251,
-                1000252,
-                1000253,
-                1000254,
-                1000255,
-                1000256,
-                1000257,
-                1000258,
-                1000259,
-                1000260,
-                1000261,
-                1000262,
-                1000263,
-                1000264,
-                1000265,
-                1000266,
-                1000267,
-                1000268,
-                1000269,
-                1000270,
-                1000271,
-                1000272,
-                1000273,
-                1000274,
-                1000275,
-                1000276,
-                1000277,
-                1000278,
-                1000279,
-                1000280,
-                1000281,
-                1000282,
-                1000283,
-                1000284,
-                1000285,
-                1000286,
-                1000287,
-                1000288,
-                1000289,
-                1000290,
-                1000291,
-                1000292,
-                1000293,
-                1000294,
-                1000295,
-                1000296,
-                1000297,
-                1000298,
-                1000299,
-                1000300,
-                1000301,
-                1000302,
-                1000303,
-                1000304,
-                1000305,
-                1000306,
-                1000307,
-                1000308,
-                1000309,
-                1000310,
-                1000311,
-                1000312,
-                1000313,
-                1000314,
-                1000315,
-                1000316,
-                1000317,
-                1000318,
-                1000319,
-                1000320,
-                1000321,
-                1000322,
-                1000323,
-                1000324,
-                1000325,
-                1000326,
-                1000327,
-                1000328,
-                1000329,
-                1000330,
-                1000331,
-                1000332,
-                1000333,
-                1000334,
-                1000335,
-                1000336,
-                1000337,
-                1000338,
-                1000339,
-                1000340,
-                1000341,
-                1000342,
-                1000343,
-                1000344,
-                1000345,
-                1000346,
-                100273,
-                100274,
-                100275,
-                100276,
-                100277,
-                100278,
-                100279,
-                100280,
-                100281,
-                100282,
-                100283,
-                100284,
-                100285,
-                100286,
-                100287,
-                100288,
-                100289,
-                100290,
-                100291,
-                100292,
-                100293,
-                100294,
-                100295,
-                100296,
-                100297,
-                100298,
-                100299,
-                100300,
-                100301,
-                100302,
-                100303,
-                100304,
-                100305,
-                100306,
-                100307,
-                100308,
-                100309,
-                100310,
-                100311,
-                100312,
-                100313,
-                100314,
-                100315,
-                100316,
-                100317,
-                100318,
-                100319,
-                100320,
-                100321,
-                100322,
-                100323,
-                100324,
-                100325,
-                100326,
-                100327,
-                100328,
-                100329,
-                100330,
-                100331,
-                100332,
-                100333,
-                100334,
-                100335,
-                100336,
-                100337,
-                100338,
-                100339,
-                100340,
-                100341,
-                100342,
-                100343,
-                100344,
-                100345,
-                100346,
-                100347
-            ],
-
-        },
-        {
-            "id": "e8X3pBZi",
-            "name": "剑指 Offer(专项突击版)",
-            "questions": [
-                1000228,
-                1000229,
-                1000230,
-                1000231,
-                1000232,
-                1000233,
-                1000234,
-                1000235,
-                1000236,
-                1000237,
-                1000238,
-                1000239,
-                1000240,
-                1000241,
-                1000242,
-                1000243,
-                1000244,
-                1000245,
-                1000246,
-                1000247,
-                1000248,
-                1000249,
-                1000250,
-                1000251,
-                1000252,
-                1000253,
-                1000254,
-                1000255,
-                1000256,
-                1000257,
-                1000258,
-                1000259,
-                1000260,
-                1000261,
-                1000262,
-                1000263,
-                1000264,
-                1000265,
-                1000266,
-                1000267,
-                1000268,
-                1000269,
-                1000270,
-                1000271,
-                1000272,
-                1000273,
-                1000274,
-                1000275,
-                1000276,
-                1000277,
-                1000278,
-                1000279,
-                1000280,
-                1000281,
-                1000282,
-                1000283,
-                1000284,
-                1000285,
-                1000286,
-                1000287,
-                1000288,
-                1000289,
-                1000290,
-                1000291,
-                1000292,
-                1000293,
-                1000294,
-                1000295,
-                1000296,
-                1000297,
-                1000298,
-                1000299,
-                1000300,
-                1000301,
-                1000302,
-                1000303,
-                1000304,
-                1000305,
-                1000306,
-                1000307,
-                1000308,
-                1000309,
-                1000310,
-                1000311,
-                1000312,
-                1000313,
-                1000314,
-                1000315,
-                1000316,
-                1000317,
-                1000318,
-                1000319,
-                1000320,
-                1000321,
-                1000322,
-                1000323,
-                1000324,
-                1000325,
-                1000326,
-                1000327,
-                1000328,
-                1000329,
-                1000330,
-                1000331,
-                1000332,
-                1000333,
-                1000334,
-                1000335,
-                1000336,
-                1000337,
-                1000338,
-                1000339,
-                1000340,
-                1000341,
-                1000342,
-                1000343,
-                1000344,
-                1000345,
-                1000346
-            ],
-
-        },
-        {
-            "id": "xb9nqhhg",
-            "name": "剑指 Offer(第 2 版)",
-            "questions": [
-                100319,
-                100328,
-                100327,
-                100326,
-                100325,
-                100324,
-                100323,
-                100322,
-                100321,
-                100320,
-                100329,
-                100318,
-                100317,
-                100316,
-                100315,
-                100314,
-                100313,
-                100312,
-                100311,
-                100338,
-                100347,
-                100346,
-                100345,
-                100344,
-                100343,
-                100342,
-                100341,
-                100340,
-                100339,
-                100310,
-                100337,
-                100336,
-                100335,
-                100334,
-                100333,
-                100332,
-                100331,
-                100330,
-                100282,
-                100291,
-                100290,
-                100289,
-                100288,
-                100287,
-                100286,
-                100285,
-                100284,
-                100283,
-                100292,
-                100281,
-                100280,
-                100279,
-                100278,
-                100277,
-                100276,
-                100275,
-                100274,
-                100301,
-                100309,
-                100308,
-                100307,
-                100306,
-                100305,
-                100304,
-                100303,
-                100302,
-                100273,
-                100300,
-                100299,
-                100298,
-                100297,
-                100296,
-                100295,
-                100294,
-                100293
-            ],
-
-        },
-        {
-            "id": "lccup",
-            "name": "力扣杯竞赛真题集",
-            "questions": [
-                1000134,
-                1000222,
-                1000362,
-                1000367,
-                1000368,
-                1000369,
-                1000370,
-                1000371,
-                1000373,
-                1000374,
-                1000375,
-                1000130,
-                1000131,
-                1000132,
-                1000133,
-                100094,
-                1000138,
-                1000139,
-                1000140,
-                1000146,
-                1000147,
-                1000056,
-                1000057,
-                1000058,
-                1000059,
-                100092,
-                100093,
-                1000062,
-                1000063,
-                1000218,
-                100107,
-                1000085,
-                1000086,
-                1000087,
-                1000088,
-                1000089,
-                1000090,
-                1000091,
-                1052,
-                1053,
-                1000093,
-                1000215,
-                1000216,
-                100096,
-                1058,
-                1059,
-                1060,
-                1061,
-                1000219,
-                1000220,
-                1000223,
-                1000224,
-                1000221,
-                1000359,
-                1000361,
-                813,
-                1069
-            ],
-
-        },
-        {
-            "id": "dynamic-programming",
-            "name": "动态规划",
-            "questions": [
-                1025,
-                514,
-                516,
-                5,
-                518,
-                10,
-                526,
-                1042,
-                1559,
-                1051,
-                32,
-                1057,
-                546,
-                1571,
-                1060,
-                549,
-                39,
-                40,
-                1063,
-                42,
-                1067,
-                1068,
-                45,
-                1583,
-                562,
-                53,
-                55,
-                568,
-                62,
-                63,
-                64,
-                576,
-                70,
-                72,
-                1105,
-                1617,
-                600,
-                91,
-                96,
-                1129,
-                1130,
-                1134,
-                115,
-                118,
-                119,
-                120,
-                121,
-                122,
-                123,
-                124,
-                634,
-                1669,
-                646,
-                647,
-                650,
-                139,
-                140,
-                651,
-                1166,
-                1680,
-                1170,
-                152,
-                664,
-                1178,
-                1690,
-                673,
-                1196,
-                174,
-                688,
-                1201,
-                1202,
-                691,
-                698,
-                188,
-                1213,
-                1220,
-                198,
-                712,
-                714,
-                1228,
-                1744,
-                1236,
-                213,
-                727,
-                1240,
-                1242,
-                221,
-                1758,
-                1250,
-                740,
-                741,
-                747,
-                238,
-                751,
-                1263,
-                1789,
-                254,
-                256,
-                1286,
-                264,
-                265,
-                1296,
-                279,
-                1822,
-                1828,
-                294,
-                298,
-                300,
-                304,
-                309,
-                312,
-                1851,
-                322,
-                1352,
-                329,
-                333,
-                337,
-                1361,
-                343,
-                351,
-                867,
-                1893,
-                361,
-                877,
-                368,
-                1906,
-                1398,
-                376,
-                377,
-                1402,
-                1403,
-                896,
-                1924,
-                392,
-                911,
-                923,
-                413,
-                1437,
-                416,
-                418,
-                930,
-                938,
-                435,
-                954,
-                446,
-                1471,
-                1474,
-                452,
-                1989,
-                967,
-                1996,
-                464,
-                977,
-                471,
-                486,
-                487,
-                494,
-                2031,
-                1008,
-                1522,
-                1013,
-                1017,
-                1531,
-                1022,
-                1535
-            ],
-
-        },
-        {
-            "id": "tusmiple",
-            "name": "图森未来",
-            "questions": [
-                718,
-                127,
-                1005,
-                1000428,
-                1000427,
-                1000426,
-                1000425,
-                1000424,
-                1000423,
-                726,
-                522,
-                973,
-                1217,
-                193,
-                1972,
-                171,
-                1957,
-                36,
-                27,
-                1294
-            ],
-
-        },
-        {
-            "id": "graph",
-            "name": "图论",
-            "questions": [
-                317,
-                1912,
-                1389,
-                877,
-                365,
-                871,
-                869,
-                1380,
-                352,
-                863,
-                323,
-                895,
-                310,
-                820,
-                305,
-                1325,
-                813,
-                803,
-                801,
-                1309,
-                1308,
-                794,
-                1986,
-                505,
-                2040,
-                2038,
-                2035,
-                499,
-                490,
-                1492,
-                1485,
-                971,
-                964,
-                1815,
-                960,
-                949,
-                433,
-                1456,
-                1447,
-                1442,
-                417,
-                922,
-                1428,
-                1100,
-                1191,
-                1701,
-                1696,
-                1171,
-                127,
-                1661,
-                1144,
-                1117,
-                1613,
-                1101,
-                1706,
-                1085,
-                1587,
-                1073,
-                1576,
-                547,
-                1058,
-                542,
-                1558,
-                1039,
-                721,
-                1300,
-                269,
-                261,
-                753,
-                744,
-                737,
-                1757,
-                733,
-                1753,
-                210,
-                1032,
-                207,
-                1229,
-                1738,
-                200,
-                1223,
-                695,
-                694,
-                685,
-                684
-            ],
-
-        },
-        {
-            "id": "bytedancecampus",
-            "name": "字节校园",
-            "questions": [
-                69,
-                88,
-                215,
-                206,
-                76,
-                200,
-                72,
-                199,
-                198,
-                92,
-                322,
-                64,
-                56,
-                54,
-                53,
-                948,
-                46,
-                300,
-                94,
-                102,
-                103,
-                232,
-                105,
-                236,
-                239,
-                1000185,
-                1000182,
-                1000183,
-                1000184,
-                121,
-                1000186,
-                1000187,
-                124,
-                135,
-                146,
-                143,
-                142,
-                15,
-                14,
-                141,
-                394,
-                1000188,
-                20,
-                7,
-                129,
-                5,
-                4,
-                3,
-                2,
-                1,
-                128,
-                21,
-                22,
-                23,
-                151,
-                25,
-                152,
-                792,
-                923,
-                31,
-                160,
-                33,
-                415,
-                41,
-                42,
-                43
-            ],
-
-        },
-        {
-            "id": "ponyai",
-            "name": "小马智行 Pony.ai",
-            "questions": [
-                15,
-                1000351,
-                1000350,
-                1000349,
-                92,
-                1000347,
-                148,
-                146,
-                1105,
-                1000352,
-                909,
-                173,
-                1000348,
-                105,
-                39,
-                1860,
-                98,
-                1441
-            ],
-
-        },
-        {
-            "id": "cmbchina-cc",
-            "name": "招商银行信用卡",
-            "questions": [
-                33,
-                124,
-                103,
-                88,
-                199,
-                198,
-                322,
-                64,
-                53,
-                41,
-                1,
-                415,
-                923,
-                22,
-                21,
-                20,
-                15,
-                7,
-                5,
-                3
-            ],
-        },
-        {
-            "id": "data-structures",
-            "name": "数据结构",
-            "questions": [
-                1,
-                2,
-                5,
-                1032,
-                15,
-                1039,
-                20,
-                21,
-                23,
-                24,
-                25,
-                547,
-                36,
-                42,
-                43,
-                44,
-                48,
-                49,
-                560,
-                53,
-                566,
-                56,
-                59,
-                1085,
-                73,
-                1609,
-                75,
-                82,
-                83,
-                84,
-                1107,
-                88,
-                94,
-                98,
-                101,
-                102,
-                103,
-                104,
-                105,
-                108,
-                112,
-                113,
-                118,
-                119,
-                121,
-                124,
-                1661,
-                128,
-                1665,
-                642,
-                136,
-                138,
-                141,
-                142,
-                143,
-                144,
-                145,
-                653,
-                148,
-                155,
-                1693,
-                160,
-                1701,
-                169,
-                173,
-                1710,
-                187,
-                199,
-                203,
-                206,
-                208,
-                1745,
-                211,
-                212,
-                214,
-                215,
-                217,
-                218,
-                729,
-                226,
-                739,
-                230,
-                232,
-                235,
-                236,
-                238,
-                1774,
-                240,
-                242,
-                761,
-                253,
-                766,
-                768,
-                261,
-                783,
-                784,
-                281,
-                290,
-                803,
-                295,
-                297,
-                305,
-                817,
-                1345,
-                323,
-                325,
-                838,
-                334,
-                336,
-                337,
-                347,
-                1371,
-                350,
-                358,
-                871,
-                366,
-                1903,
-                369,
-                378,
-                892,
-                383,
-                387,
-                394,
-                402,
-                409,
-                922,
-                415,
-                1951,
-                1442,
-                1450,
-                435,
-                448,
-                450,
-                451,
-                452,
-                454,
-                456,
-                2009,
-                1008,
-                1014
-            ],
-
-        },
-        {
-            "id": "xb9lfcwi",
-            "name": "程序员面试金典(第 6 版)",
-            "questions": [
-                100352,
-                100353,
-                100354,
-                100355,
-                100356,
-                1000003,
-                1000004,
-                1000005,
-                1000006,
-                1000007,
-                1000008,
-                1000009,
-                1000010,
-                1000011,
-                1000012,
-                1000013,
-                1000015,
-                1000016,
-                1000017,
-                1000018,
-                1000019,
-                1000020,
-                1000021,
-                1000022,
-                1000023,
-                1000024,
-                1000025,
-                1000026,
-                1000027,
-                1000028,
-                1000029,
-                1000030,
-                1000031,
-                1000032,
-                1000033,
-                1000034,
-                1000035,
-                1000036,
-                1000037,
-                1000038,
-                1000039,
-                1000040,
-                1000041,
-                1000042,
-                1000043,
-                1000044,
-                1000045,
-                1000046,
-                1000047,
-                1000048,
-                1000049,
-                1000050,
-                1000051,
-                100158,
-                100159,
-                100160,
-                100161,
-                100162,
-                100163,
-                100164,
-                100167,
-                100168,
-                100169,
-                100170,
-                100171,
-                100172,
-                100173,
-                100174,
-                100175,
-                100176,
-                100177,
-                100178,
-                100179,
-                100180,
-                100181,
-                100182,
-                100183,
-                100184,
-                100185,
-                100186,
-                100187,
-                100188,
-                100195,
-                100196,
-                100197,
-                100198,
-                100199,
-                100200,
-                100201,
-                100202,
-                100203,
-                100228,
-                100229,
-                100230,
-                100231,
-                100232,
-                100233,
-                100240,
-                100241,
-                100242,
-                100258,
-                100259,
-                100260,
-                100261,
-                100262,
-                100348,
-                100349,
-                100350,
-                100351
-            ],
-
-        },
-        {
-            "id": "algorithms",
-            "name": "算法",
-            "questions": [
-                1025,
-                3,
-                4,
-                5,
-                1028,
-                10,
-                11,
-                1036,
-                1037,
-                15,
-                17,
-                19,
-                21,
-                22,
-                1046,
-                542,
-                33,
-                34,
-                35,
-                547,
-                37,
-                1059,
-                39,
-                40,
-                42,
-                45,
-                46,
-                47,
-                557,
-                51,
-                53,
-                55,
-                567,
-                2047,
-                572,
-                62,
-                70,
-                582,
-                72,
-                583,
-                74,
-                1609,
-                76,
-                77,
-                78,
-                79,
-                1101,
-                82,
-                85,
-                90,
-                91,
-                617,
-                1134,
-                116,
-                117,
-                120,
-                123,
-                130,
-                131,
-                132,
-                136,
-                139,
-                1165,
-                146,
-                1171,
-                149,
-                153,
-                159,
-                673,
-                162,
-                167,
-                1192,
-                174,
-                695,
-                189,
-                190,
-                191,
-                198,
-                200,
-                201,
-                202,
-                713,
-                714,
-                715,
-                206,
-                207,
-                209,
-                210,
-                213,
-                221,
-                733,
-                1250,
-                231,
-                239,
-                241,
-                753,
-                254,
-                260,
-                269,
-                1300,
-                278,
-                792,
-                283,
-                286,
-                287,
-                800,
-                300,
-                301,
-                813,
-                309,
-                310,
-                315,
-                322,
-                329,
-                337,
-                340,
-                343,
-                344,
-                865,
-                874,
-                893,
-                895,
-                384,
-                394,
-                908,
-                410,
-                413,
-                416,
-                417,
-                1442,
-                438,
-                460,
-                1485,
-                2019,
-                486,
-                1512,
-                1019,
-                1023
-            ],
-
-        },
-        {
-            "id": "programming-skills",
-            "name": "编程能力",
-            "questions": [
-                2,
-                1031,
-                8,
-                525,
-                23,
-                535,
-                28,
-                43,
-                556,
-                48,
-                49,
-                1584,
-                54,
-                566,
-                58,
-                61,
-                65,
-                66,
-                67,
-                1626,
-                1630,
-                1125,
-                104,
-                110,
-                631,
-                635,
-                642,
-                138,
-                1677,
-                143,
-                146,
-                148,
-                150,
-                1176,
-                155,
-                1693,
-                1708,
-                173,
-                1713,
-                191,
-                1728,
-                1729,
-                1736,
-                713,
-                202,
-                715,
-                208,
-                209,
-                211,
-                214,
-                1752,
-                217,
-                729,
-                224,
-                227,
-                739,
-                742,
-                232,
-                1768,
-                1774,
-                241,
-                242,
-                244,
-                758,
-                251,
-                764,
-                255,
-                1791,
-                771,
-                1797,
-                775,
-                785,
-                2322,
-                281,
-                282,
-                283,
-                295,
-                297,
-                303,
-                304,
-                307,
-                325,
-                838,
-                1349,
-                850,
-                341,
-                859,
-                348,
-                860,
-                1888,
-                353,
-                1894,
-                369,
-                1905,
-                885,
-                890,
-                1915,
-                380,
-                381,
-                1406,
-                1411,
-                389,
-                1930,
-                908,
-                404,
-                1434,
-                1949,
-                1950,
-                931,
-                932,
-                1955,
-                937,
-                946,
-                1458,
-                438,
-                445,
-                1982,
-                449,
-                1477,
-                459,
-                460,
-                1484,
-                1492,
-                990,
-                2015,
-                1512,
-                496,
-                1014,
-                503,
-                1018
-            ],
-
-        },
-        {
-            "id": "meituan",
-            "name": "美团真题",
-            "questions": [
-                1000192,
-                1000193,
-                1000194,
-                1000195,
-                1000196,
-                1000197,
-                1000198,
-                1000199,
-                1000200,
-                1000201,
-                1000202,
-                1000203,
-                1000189,
-                1000190,
-                1000191,
-                257,
-                100158,
-                13,
-                455,
-                45,
-                200,
-                143,
-                139,
-                19,
-                100344,
-                162,
-                177,
-                75,
-                1036,
-                71,
-                475,
-                42,
-                51,
-                440,
-                25
-            ],
-
-        },
-        {
-            "id": "ke",
-            "name": "贝壳找房",
-            "questions": [
-                30,
-                120,
-                113,
-                85,
-                82,
-                209,
-                200,
-                315,
-                56,
-                53,
-                43,
-                2,
-                152,
-                20,
-                19,
-                17,
-                15,
-                14,
-                264,
-                135,
-                4
-            ],
-
-        },
-        {
-            "id": "efficient-winning",
-            "name": "高效制胜",
-            "questions": [
-                230,
-                329,
-                79,
-                720,
-                218,
-                1120,
-                97,
-                483,
-                1508,
-                456,
-                112,
-                496,
-                1008,
-                1013,
-                119,
-                121,
-                122,
-                416,
-                3,
-                11,
-                524,
-                15,
-                18,
-                20,
-                279,
-                28,
-                1,
-                803,
-                167,
-                42,
-                53,
-                825,
-                322,
-                70
-            ],
-
-        },
-        {
-            "id": "2cktkvj",
-            "name": "LeetCode 热题 HOT 100",
-            "questions": [
-                160,
-                236,
-                234,
-                739,
-                226,
-                221,
-                215,
-                208,
-                207,
-                206,
-                200,
-                198,
-                169,
-                238,
-                155,
-                152,
-                148,
-                146,
-                142,
-                141,
-                139,
-                136,
-                647,
-                128,
-                124,
-                322,
-                494,
-                461,
-                448,
-                438,
-                437,
-                416,
-                406,
-                399,
-                394,
-                347,
-                338,
-                337,
-                121,
-                312,
-                309,
-                301,
-                300,
-                297,
-                287,
-                283,
-                279,
-                253,
-                240,
-                239,
-                22,
-                49,
-                48,
-                46,
-                42,
-                39,
-                543,
-                34,
-                33,
-                32,
-                31,
-                538,
-                23,
-                560,
-                21,
-                20,
-                19,
-                17,
-                15,
-                11,
-                10,
-                5,
-                4,
-                3,
-                2,
-                79,
-                114,
-                621,
-                617,
-                105,
-                104,
-                102,
-                101,
-                98,
-                96,
-                94,
-                85,
-                84,
-                1,
-                78,
-                76,
-                75,
-                72,
-                70,
-                581,
-                64,
-                62,
-                56,
-                55,
-                53
-            ],
-
-        },
-        {
-            "id": "7cyqwuv",
-            "name": "力扣杯 - 竞赛合集",
-            "questions": [
-                1000134,
-                1000222,
-                1000362,
-                1000367,
-                1000368,
-                1000369,
-                1000370,
-                1000371,
-                1000373,
-                1000374,
-                1000375,
-                1000130,
-                1000131,
-                1000132,
-                1000133,
-                100094,
-                1000138,
-                1000139,
-                1000140,
-                1000146,
-                1000147,
-                1000056,
-                1000057,
-                1000058,
-                1000059,
-                100092,
-                100093,
-                1000062,
-                1000063,
-                1000216,
-                100107,
-                511,
-                1000085,
-                1000086,
-                1000087,
-                1000088,
-                1000089,
-                1000090,
-                1000091,
-                1052,
-                1053,
-                1000093,
-                1000215,
-                100096,
-                1000218,
-                1058,
-                1059,
-                1060,
-                1061,
-                1000219,
-                1000220,
-                1000223,
-                1000224,
-                1000221,
-                1000359,
-                1000361,
-                1069
-            ],
-
-        },
-        {
-            "id": "ex0k24j",
-            "name": "腾讯精选练习 50 题",
-            "questions": [
-                217,
-                46,
-                53,
-                54,
-                59,
-                61,
-                62,
-                70,
-                78,
-                206,
-                215,
-                88,
-                89,
-                557,
-                344,
-                230,
-                231,
-                104,
-                235,
-                236,
-                237,
-                238,
-                121,
-                122,
-                124,
-                146,
-                4,
-                5,
-                7,
-                8,
-                9,
-                136,
-                11,
-                141,
-                14,
-                15,
-                16,
-                142,
-                2,
-                20,
-                21,
-                148,
-                23,
-                26,
-                155,
-                160,
-                33,
-                292,
-                169,
-                43
-            ],
-
-        },
-        {
-            "id": "2ckc81c",
-            "name": "LeetCode 精选 TOP 面试题",
-            "questions": [
-                1,
-                2,
-                3,
-                4,
-                5,
-                7,
-                8,
-                10,
-                11,
-                13,
-                14,
-                15,
-                17,
-                19,
-                20,
-                21,
-                22,
-                23,
-                26,
-                28,
-                29,
-                33,
-                34,
-                36,
-                38,
-                41,
-                42,
-                44,
-                46,
-                48,
-                49,
-                50,
-                53,
-                54,
-                55,
-                56,
-                62,
-                66,
-                69,
-                70,
-                73,
-                75,
-                76,
-                78,
-                79,
-                84,
-                88,
-                91,
-                94,
-                98,
-                101,
-                102,
-                103,
-                104,
-                105,
-                108,
-                116,
-                118,
-                121,
-                122,
-                124,
-                125,
-                127,
-                128,
-                130,
-                131,
-                134,
-                136,
-                138,
-                139,
-                140,
-                141,
-                146,
-                148,
-                149,
-                150,
-                152,
-                155,
-                160,
-                162,
-                163,
-                166,
-                169,
-                171,
-                172,
-                179,
-                189,
-                190,
-                191,
-                198,
-                200,
-                202,
-                204,
-                206,
-                207,
-                208,
-                210,
-                212,
-                215,
-                217,
-                218,
-                227,
-                230,
-                234,
-                236,
-                237,
-                238,
-                239,
-                240,
-                242,
-                251,
-                253,
-                268,
-                269,
-                277,
-                279,
-                283,
-                285,
-                287,
-                289,
-                295,
-                297,
-                300,
-                308,
-                315,
-                322,
-                324,
-                326,
-                328,
-                329,
-                334,
-                340,
-                341,
-                344,
-                347,
-                348,
-                350,
-                371,
-                378,
-                380,
-                384,
-                387,
-                395,
-                412,
-                454
-            ],
-
-        }
-    ];
+  public getChoiceData() {
+    return this.choiceData;
+  }
+
+  private choiceData = [
+    {
+      id: "shopee",
+      name: "Shopee精选",
+      questions: [
+        341, 1000447, 1000446, 1000445, 1000444, 1000443, 232, 871, 102, 101, 15, 460, 456, 448, 179, 432, 48, 37, 20,
+        146,
+      ],
+    },
+    {
+      id: "binary-search",
+      name: "二分查找",
+      questions: [
+        4, 1550, 540, 1056, 33, 34, 35, 1059, 1060, 1083, 2047, 69, 1605, 74, 1612, 1102, 1615, 81, 1621, 1122, 611,
+        1645, 1134, 1646, 1143, 633, 1149, 644, 1672, 1675, 1679, 658, 1684, 153, 154, 668, 1185, 162, 167, 1192, 1730,
+        718, 719, 1232, 209, 1753, 222, 1249, 1766, 745, 1771, 1262, 240, 1290, 270, 786, 275, 788, 278, 792, 794, 1307,
+        287, 802, 1831, 1832, 809, 300, 302, 1326, 1851, 1352, 853, 350, 1374, 352, 1886, 1891, 1384, 363, 367, 882,
+        374, 378, 894, 1918, 1408, 1413, 1929, 907, 912, 1946, 923, 1957, 1966, 947, 436, 1463, 441, 1468, 1984, 1476,
+        1486, 2000, 2006, 2018, 2027, 2036, 2045, 1023,
+      ],
+    },
+    {
+      id: "lcof",
+      name: "剑指 Offer",
+      questions: [
+        1000228, 1000229, 1000230, 1000231, 1000232, 1000233, 1000234, 1000235, 1000236, 1000237, 1000238, 1000239,
+        1000240, 1000241, 1000242, 1000243, 1000244, 1000245, 1000246, 1000247, 1000248, 1000249, 1000250, 1000251,
+        1000252, 1000253, 1000254, 1000255, 1000256, 1000257, 1000258, 1000259, 1000260, 1000261, 1000262, 1000263,
+        1000264, 1000265, 1000266, 1000267, 1000268, 1000269, 1000270, 1000271, 1000272, 1000273, 1000274, 1000275,
+        1000276, 1000277, 1000278, 1000279, 1000280, 1000281, 1000282, 1000283, 1000284, 1000285, 1000286, 1000287,
+        1000288, 1000289, 1000290, 1000291, 1000292, 1000293, 1000294, 1000295, 1000296, 1000297, 1000298, 1000299,
+        1000300, 1000301, 1000302, 1000303, 1000304, 1000305, 1000306, 1000307, 1000308, 1000309, 1000310, 1000311,
+        1000312, 1000313, 1000314, 1000315, 1000316, 1000317, 1000318, 1000319, 1000320, 1000321, 1000322, 1000323,
+        1000324, 1000325, 1000326, 1000327, 1000328, 1000329, 1000330, 1000331, 1000332, 1000333, 1000334, 1000335,
+        1000336, 1000337, 1000338, 1000339, 1000340, 1000341, 1000342, 1000343, 1000344, 1000345, 1000346, 100273,
+        100274, 100275, 100276, 100277, 100278, 100279, 100280, 100281, 100282, 100283, 100284, 100285, 100286, 100287,
+        100288, 100289, 100290, 100291, 100292, 100293, 100294, 100295, 100296, 100297, 100298, 100299, 100300, 100301,
+        100302, 100303, 100304, 100305, 100306, 100307, 100308, 100309, 100310, 100311, 100312, 100313, 100314, 100315,
+        100316, 100317, 100318, 100319, 100320, 100321, 100322, 100323, 100324, 100325, 100326, 100327, 100328, 100329,
+        100330, 100331, 100332, 100333, 100334, 100335, 100336, 100337, 100338, 100339, 100340, 100341, 100342, 100343,
+        100344, 100345, 100346, 100347,
+      ],
+    },
+    {
+      id: "e8X3pBZi",
+      name: "剑指 Offer(专项突击版)",
+      questions: [
+        1000228, 1000229, 1000230, 1000231, 1000232, 1000233, 1000234, 1000235, 1000236, 1000237, 1000238, 1000239,
+        1000240, 1000241, 1000242, 1000243, 1000244, 1000245, 1000246, 1000247, 1000248, 1000249, 1000250, 1000251,
+        1000252, 1000253, 1000254, 1000255, 1000256, 1000257, 1000258, 1000259, 1000260, 1000261, 1000262, 1000263,
+        1000264, 1000265, 1000266, 1000267, 1000268, 1000269, 1000270, 1000271, 1000272, 1000273, 1000274, 1000275,
+        1000276, 1000277, 1000278, 1000279, 1000280, 1000281, 1000282, 1000283, 1000284, 1000285, 1000286, 1000287,
+        1000288, 1000289, 1000290, 1000291, 1000292, 1000293, 1000294, 1000295, 1000296, 1000297, 1000298, 1000299,
+        1000300, 1000301, 1000302, 1000303, 1000304, 1000305, 1000306, 1000307, 1000308, 1000309, 1000310, 1000311,
+        1000312, 1000313, 1000314, 1000315, 1000316, 1000317, 1000318, 1000319, 1000320, 1000321, 1000322, 1000323,
+        1000324, 1000325, 1000326, 1000327, 1000328, 1000329, 1000330, 1000331, 1000332, 1000333, 1000334, 1000335,
+        1000336, 1000337, 1000338, 1000339, 1000340, 1000341, 1000342, 1000343, 1000344, 1000345, 1000346,
+      ],
+    },
+    {
+      id: "xb9nqhhg",
+      name: "剑指 Offer(第 2 版)",
+      questions: [
+        100319, 100328, 100327, 100326, 100325, 100324, 100323, 100322, 100321, 100320, 100329, 100318, 100317, 100316,
+        100315, 100314, 100313, 100312, 100311, 100338, 100347, 100346, 100345, 100344, 100343, 100342, 100341, 100340,
+        100339, 100310, 100337, 100336, 100335, 100334, 100333, 100332, 100331, 100330, 100282, 100291, 100290, 100289,
+        100288, 100287, 100286, 100285, 100284, 100283, 100292, 100281, 100280, 100279, 100278, 100277, 100276, 100275,
+        100274, 100301, 100309, 100308, 100307, 100306, 100305, 100304, 100303, 100302, 100273, 100300, 100299, 100298,
+        100297, 100296, 100295, 100294, 100293,
+      ],
+    },
+    {
+      id: "lccup",
+      name: "力扣杯竞赛真题集",
+      questions: [
+        1000134, 1000222, 1000362, 1000367, 1000368, 1000369, 1000370, 1000371, 1000373, 1000374, 1000375, 1000130,
+        1000131, 1000132, 1000133, 100094, 1000138, 1000139, 1000140, 1000146, 1000147, 1000056, 1000057, 1000058,
+        1000059, 100092, 100093, 1000062, 1000063, 1000218, 100107, 1000085, 1000086, 1000087, 1000088, 1000089,
+        1000090, 1000091, 1052, 1053, 1000093, 1000215, 1000216, 100096, 1058, 1059, 1060, 1061, 1000219, 1000220,
+        1000223, 1000224, 1000221, 1000359, 1000361, 813, 1069,
+      ],
+    },
+    {
+      id: "dynamic-programming",
+      name: "动态规划",
+      questions: [
+        1025, 514, 516, 5, 518, 10, 526, 1042, 1559, 1051, 32, 1057, 546, 1571, 1060, 549, 39, 40, 1063, 42, 1067, 1068,
+        45, 1583, 562, 53, 55, 568, 62, 63, 64, 576, 70, 72, 1105, 1617, 600, 91, 96, 1129, 1130, 1134, 115, 118, 119,
+        120, 121, 122, 123, 124, 634, 1669, 646, 647, 650, 139, 140, 651, 1166, 1680, 1170, 152, 664, 1178, 1690, 673,
+        1196, 174, 688, 1201, 1202, 691, 698, 188, 1213, 1220, 198, 712, 714, 1228, 1744, 1236, 213, 727, 1240, 1242,
+        221, 1758, 1250, 740, 741, 747, 238, 751, 1263, 1789, 254, 256, 1286, 264, 265, 1296, 279, 1822, 1828, 294, 298,
+        300, 304, 309, 312, 1851, 322, 1352, 329, 333, 337, 1361, 343, 351, 867, 1893, 361, 877, 368, 1906, 1398, 376,
+        377, 1402, 1403, 896, 1924, 392, 911, 923, 413, 1437, 416, 418, 930, 938, 435, 954, 446, 1471, 1474, 452, 1989,
+        967, 1996, 464, 977, 471, 486, 487, 494, 2031, 1008, 1522, 1013, 1017, 1531, 1022, 1535,
+      ],
+    },
+    {
+      id: "tusmiple",
+      name: "图森未来",
+      questions: [
+        718, 127, 1005, 1000428, 1000427, 1000426, 1000425, 1000424, 1000423, 726, 522, 973, 1217, 193, 1972, 171, 1957,
+        36, 27, 1294,
+      ],
+    },
+    {
+      id: "graph",
+      name: "图论",
+      questions: [
+        317, 1912, 1389, 877, 365, 871, 869, 1380, 352, 863, 323, 895, 310, 820, 305, 1325, 813, 803, 801, 1309, 1308,
+        794, 1986, 505, 2040, 2038, 2035, 499, 490, 1492, 1485, 971, 964, 1815, 960, 949, 433, 1456, 1447, 1442, 417,
+        922, 1428, 1100, 1191, 1701, 1696, 1171, 127, 1661, 1144, 1117, 1613, 1101, 1706, 1085, 1587, 1073, 1576, 547,
+        1058, 542, 1558, 1039, 721, 1300, 269, 261, 753, 744, 737, 1757, 733, 1753, 210, 1032, 207, 1229, 1738, 200,
+        1223, 695, 694, 685, 684,
+      ],
+    },
+    {
+      id: "bytedancecampus",
+      name: "字节校园",
+      questions: [
+        69, 88, 215, 206, 76, 200, 72, 199, 198, 92, 322, 64, 56, 54, 53, 948, 46, 300, 94, 102, 103, 232, 105, 236,
+        239, 1000185, 1000182, 1000183, 1000184, 121, 1000186, 1000187, 124, 135, 146, 143, 142, 15, 14, 141, 394,
+        1000188, 20, 7, 129, 5, 4, 3, 2, 1, 128, 21, 22, 23, 151, 25, 152, 792, 923, 31, 160, 33, 415, 41, 42, 43,
+      ],
+    },
+    {
+      id: "ponyai",
+      name: "小马智行 Pony.ai",
+      questions: [
+        15, 1000351, 1000350, 1000349, 92, 1000347, 148, 146, 1105, 1000352, 909, 173, 1000348, 105, 39, 1860, 98, 1441,
+      ],
+    },
+    {
+      id: "cmbchina-cc",
+      name: "招商银行信用卡",
+      questions: [33, 124, 103, 88, 199, 198, 322, 64, 53, 41, 1, 415, 923, 22, 21, 20, 15, 7, 5, 3],
+    },
+    {
+      id: "data-structures",
+      name: "数据结构",
+      questions: [
+        1, 2, 5, 1032, 15, 1039, 20, 21, 23, 24, 25, 547, 36, 42, 43, 44, 48, 49, 560, 53, 566, 56, 59, 1085, 73, 1609,
+        75, 82, 83, 84, 1107, 88, 94, 98, 101, 102, 103, 104, 105, 108, 112, 113, 118, 119, 121, 124, 1661, 128, 1665,
+        642, 136, 138, 141, 142, 143, 144, 145, 653, 148, 155, 1693, 160, 1701, 169, 173, 1710, 187, 199, 203, 206, 208,
+        1745, 211, 212, 214, 215, 217, 218, 729, 226, 739, 230, 232, 235, 236, 238, 1774, 240, 242, 761, 253, 766, 768,
+        261, 783, 784, 281, 290, 803, 295, 297, 305, 817, 1345, 323, 325, 838, 334, 336, 337, 347, 1371, 350, 358, 871,
+        366, 1903, 369, 378, 892, 383, 387, 394, 402, 409, 922, 415, 1951, 1442, 1450, 435, 448, 450, 451, 452, 454,
+        456, 2009, 1008, 1014,
+      ],
+    },
+    {
+      id: "xb9lfcwi",
+      name: "程序员面试金典(第 6 版)",
+      questions: [
+        100352, 100353, 100354, 100355, 100356, 1000003, 1000004, 1000005, 1000006, 1000007, 1000008, 1000009, 1000010,
+        1000011, 1000012, 1000013, 1000015, 1000016, 1000017, 1000018, 1000019, 1000020, 1000021, 1000022, 1000023,
+        1000024, 1000025, 1000026, 1000027, 1000028, 1000029, 1000030, 1000031, 1000032, 1000033, 1000034, 1000035,
+        1000036, 1000037, 1000038, 1000039, 1000040, 1000041, 1000042, 1000043, 1000044, 1000045, 1000046, 1000047,
+        1000048, 1000049, 1000050, 1000051, 100158, 100159, 100160, 100161, 100162, 100163, 100164, 100167, 100168,
+        100169, 100170, 100171, 100172, 100173, 100174, 100175, 100176, 100177, 100178, 100179, 100180, 100181, 100182,
+        100183, 100184, 100185, 100186, 100187, 100188, 100195, 100196, 100197, 100198, 100199, 100200, 100201, 100202,
+        100203, 100228, 100229, 100230, 100231, 100232, 100233, 100240, 100241, 100242, 100258, 100259, 100260, 100261,
+        100262, 100348, 100349, 100350, 100351,
+      ],
+    },
+    {
+      id: "algorithms",
+      name: "算法",
+      questions: [
+        1025, 3, 4, 5, 1028, 10, 11, 1036, 1037, 15, 17, 19, 21, 22, 1046, 542, 33, 34, 35, 547, 37, 1059, 39, 40, 42,
+        45, 46, 47, 557, 51, 53, 55, 567, 2047, 572, 62, 70, 582, 72, 583, 74, 1609, 76, 77, 78, 79, 1101, 82, 85, 90,
+        91, 617, 1134, 116, 117, 120, 123, 130, 131, 132, 136, 139, 1165, 146, 1171, 149, 153, 159, 673, 162, 167, 1192,
+        174, 695, 189, 190, 191, 198, 200, 201, 202, 713, 714, 715, 206, 207, 209, 210, 213, 221, 733, 1250, 231, 239,
+        241, 753, 254, 260, 269, 1300, 278, 792, 283, 286, 287, 800, 300, 301, 813, 309, 310, 315, 322, 329, 337, 340,
+        343, 344, 865, 874, 893, 895, 384, 394, 908, 410, 413, 416, 417, 1442, 438, 460, 1485, 2019, 486, 1512, 1019,
+        1023,
+      ],
+    },
+    {
+      id: "programming-skills",
+      name: "编程能力",
+      questions: [
+        2, 1031, 8, 525, 23, 535, 28, 43, 556, 48, 49, 1584, 54, 566, 58, 61, 65, 66, 67, 1626, 1630, 1125, 104, 110,
+        631, 635, 642, 138, 1677, 143, 146, 148, 150, 1176, 155, 1693, 1708, 173, 1713, 191, 1728, 1729, 1736, 713, 202,
+        715, 208, 209, 211, 214, 1752, 217, 729, 224, 227, 739, 742, 232, 1768, 1774, 241, 242, 244, 758, 251, 764, 255,
+        1791, 771, 1797, 775, 785, 2322, 281, 282, 283, 295, 297, 303, 304, 307, 325, 838, 1349, 850, 341, 859, 348,
+        860, 1888, 353, 1894, 369, 1905, 885, 890, 1915, 380, 381, 1406, 1411, 389, 1930, 908, 404, 1434, 1949, 1950,
+        931, 932, 1955, 937, 946, 1458, 438, 445, 1982, 449, 1477, 459, 460, 1484, 1492, 990, 2015, 1512, 496, 1014,
+        503, 1018,
+      ],
+    },
+    {
+      id: "meituan",
+      name: "美团真题",
+      questions: [
+        1000192, 1000193, 1000194, 1000195, 1000196, 1000197, 1000198, 1000199, 1000200, 1000201, 1000202, 1000203,
+        1000189, 1000190, 1000191, 257, 100158, 13, 455, 45, 200, 143, 139, 19, 100344, 162, 177, 75, 1036, 71, 475, 42,
+        51, 440, 25,
+      ],
+    },
+    {
+      id: "ke",
+      name: "贝壳找房",
+      questions: [30, 120, 113, 85, 82, 209, 200, 315, 56, 53, 43, 2, 152, 20, 19, 17, 15, 14, 264, 135, 4],
+    },
+    {
+      id: "efficient-winning",
+      name: "高效制胜",
+      questions: [
+        230, 329, 79, 720, 218, 1120, 97, 483, 1508, 456, 112, 496, 1008, 1013, 119, 121, 122, 416, 3, 11, 524, 15, 18,
+        20, 279, 28, 1, 803, 167, 42, 53, 825, 322, 70,
+      ],
+    },
+    {
+      id: "2cktkvj",
+      name: "LeetCode 热题 HOT 100",
+      questions: [
+        160, 236, 234, 739, 226, 221, 215, 208, 207, 206, 200, 198, 169, 238, 155, 152, 148, 146, 142, 141, 139, 136,
+        647, 128, 124, 322, 494, 461, 448, 438, 437, 416, 406, 399, 394, 347, 338, 337, 121, 312, 309, 301, 300, 297,
+        287, 283, 279, 253, 240, 239, 22, 49, 48, 46, 42, 39, 543, 34, 33, 32, 31, 538, 23, 560, 21, 20, 19, 17, 15, 11,
+        10, 5, 4, 3, 2, 79, 114, 621, 617, 105, 104, 102, 101, 98, 96, 94, 85, 84, 1, 78, 76, 75, 72, 70, 581, 64, 62,
+        56, 55, 53,
+      ],
+    },
+    {
+      id: "7cyqwuv",
+      name: "力扣杯 - 竞赛合集",
+      questions: [
+        1000134, 1000222, 1000362, 1000367, 1000368, 1000369, 1000370, 1000371, 1000373, 1000374, 1000375, 1000130,
+        1000131, 1000132, 1000133, 100094, 1000138, 1000139, 1000140, 1000146, 1000147, 1000056, 1000057, 1000058,
+        1000059, 100092, 100093, 1000062, 1000063, 1000216, 100107, 511, 1000085, 1000086, 1000087, 1000088, 1000089,
+        1000090, 1000091, 1052, 1053, 1000093, 1000215, 100096, 1000218, 1058, 1059, 1060, 1061, 1000219, 1000220,
+        1000223, 1000224, 1000221, 1000359, 1000361, 1069,
+      ],
+    },
+    {
+      id: "ex0k24j",
+      name: "腾讯精选练习 50 题",
+      questions: [
+        217, 46, 53, 54, 59, 61, 62, 70, 78, 206, 215, 88, 89, 557, 344, 230, 231, 104, 235, 236, 237, 238, 121, 122,
+        124, 146, 4, 5, 7, 8, 9, 136, 11, 141, 14, 15, 16, 142, 2, 20, 21, 148, 23, 26, 155, 160, 33, 292, 169, 43,
+      ],
+    },
+    {
+      id: "2ckc81c",
+      name: "LeetCode 精选 TOP 面试题",
+      questions: [
+        1, 2, 3, 4, 5, 7, 8, 10, 11, 13, 14, 15, 17, 19, 20, 21, 22, 23, 26, 28, 29, 33, 34, 36, 38, 41, 42, 44, 46, 48,
+        49, 50, 53, 54, 55, 56, 62, 66, 69, 70, 73, 75, 76, 78, 79, 84, 88, 91, 94, 98, 101, 102, 103, 104, 105, 108,
+        116, 118, 121, 122, 124, 125, 127, 128, 130, 131, 134, 136, 138, 139, 140, 141, 146, 148, 149, 150, 152, 155,
+        160, 162, 163, 166, 169, 171, 172, 179, 189, 190, 191, 198, 200, 202, 204, 206, 207, 208, 210, 212, 215, 217,
+        218, 227, 230, 234, 236, 237, 238, 239, 240, 242, 251, 253, 268, 269, 277, 279, 283, 285, 287, 289, 295, 297,
+        300, 308, 315, 322, 324, 326, 328, 329, 334, 340, 341, 344, 347, 348, 350, 371, 378, 380, 384, 387, 395, 412,
+        454,
+      ],
+    },
+  ];
 }
 
-
 export const choiceDao: ChoiceDao = new ChoiceDao();
-
-
-
-
-
-
diff --git a/src/dao/scoreDao.ts b/src/dao/scoreDao.ts
index 211ac43..e737d86 100644
--- a/src/dao/scoreDao.ts
+++ b/src/dao/scoreDao.ts
@@ -9,35 +9,24 @@
 
 import { IScoreData } from "../model/Model";
 
-
-
-
 class ScoreDao {
-    private scoreBase = require("../../../resources/data.json");
+  private scoreBase = require("../../../resources/data.json");
 
-    public getScoreData(onlineData?): Map {
-
-        let nameSiteMapping = new Map();
-        let temp = this.scoreBase as IScoreData[];
-        if (onlineData) {
-            temp = onlineData;
-        }
-        temp.forEach(element => {
-            // Rating
-            // ID
-            // ContestSlug
-            element.score = "" + Math.floor(element.Rating || 0);
-            nameSiteMapping.set("" + element.ID, element);
-        });
-        return nameSiteMapping;
+  public getScoreData(onlineData?): Map {
+    let nameSiteMapping = new Map();
+    let temp = this.scoreBase as IScoreData[];
+    if (onlineData) {
+      temp = onlineData;
     }
+    temp.forEach((element) => {
+      // Rating
+      // ID
+      // ContestSlug
+      element.score = "" + Math.floor(element.Rating || 0);
+      nameSiteMapping.set("" + element.ID, element);
+    });
+    return nameSiteMapping;
+  }
 }
 
-
 export const scoreDao: ScoreDao = new ScoreDao();
-
-
-
-
-
-
diff --git a/src/dao/tagsDao.ts b/src/dao/tagsDao.ts
index 42ee915..eeca573 100644
--- a/src/dao/tagsDao.ts
+++ b/src/dao/tagsDao.ts
@@ -7,2892 +7,4676 @@
  * Copyright (c) 2022 ccagml . All rights reserved.
  */
 
-
-
 class TagsDao {
+  private tagsData = {
+    "1": { topicTags: ["array", "hash-table"] },
+    "2": { topicTags: ["recursion", "linked-list", "math"] },
+    "3": { topicTags: ["hash-table", "string", "sliding-window"] },
+    "4": { topicTags: ["array", "binary-search", "divide-and-conquer"] },
+    "5": { topicTags: ["string", "dynamic-programming"] },
+    "6": { topicTags: ["string"] },
+    "7": { topicTags: ["math"] },
+    "8": { topicTags: ["string"] },
+    "9": { topicTags: ["math"] },
+    "10": { topicTags: ["recursion", "string", "dynamic-programming"] },
+    "11": { topicTags: ["greedy", "array", "two-pointers"] },
+    "12": { topicTags: ["hash-table", "math", "string"] },
+    "13": { topicTags: ["hash-table", "math", "string"] },
+    "14": { topicTags: ["string"] },
+    "15": { topicTags: ["array", "two-pointers", "sorting"] },
+    "16": { topicTags: ["array", "two-pointers", "sorting"] },
+    "17": { topicTags: ["hash-table", "string", "backtracking"] },
+    "18": { topicTags: ["array", "two-pointers", "sorting"] },
+    "19": { topicTags: ["linked-list", "two-pointers"] },
+    "20": { topicTags: ["stack", "string"] },
+    "21": { topicTags: ["recursion", "linked-list"] },
+    "22": { topicTags: ["string", "dynamic-programming", "backtracking"] },
+    "23": {
+      topicTags: ["linked-list", "divide-and-conquer", "heap-priority-queue", "merge-sort"],
+    },
+    "24": { topicTags: ["recursion", "linked-list"] },
+    "25": { topicTags: ["recursion", "linked-list"] },
+    "26": { topicTags: ["array", "two-pointers"] },
+    "27": { topicTags: ["array", "two-pointers"] },
+    "28": { topicTags: ["two-pointers", "string", "string-matching"] },
+    "29": { topicTags: ["bit-manipulation", "math"] },
+    "30": { topicTags: ["hash-table", "string", "sliding-window"] },
+    "31": { topicTags: ["array", "two-pointers"] },
+    "32": { topicTags: ["stack", "string", "dynamic-programming"] },
+    "33": { topicTags: ["array", "binary-search"] },
+    "34": { topicTags: ["array", "binary-search"] },
+    "35": { topicTags: ["array", "binary-search"] },
+    "36": { topicTags: ["array", "hash-table", "matrix"] },
+    "37": { topicTags: ["array", "backtracking", "matrix"] },
+    "38": { topicTags: ["string"] },
+    "39": { topicTags: ["array", "backtracking"] },
+    "40": { topicTags: ["array", "backtracking"] },
+    "41": { topicTags: ["array", "hash-table"] },
+    "42": {
+      topicTags: ["stack", "array", "two-pointers", "dynamic-programming", "monotonic-stack"],
+    },
+    "43": { topicTags: ["math", "string", "simulation"] },
+    "44": {
+      topicTags: ["greedy", "recursion", "string", "dynamic-programming"],
+    },
+    "45": { topicTags: ["greedy", "array", "dynamic-programming"] },
+    "46": { topicTags: ["array", "backtracking"] },
+    "47": { topicTags: ["array", "backtracking"] },
+    "48": { topicTags: ["array", "math", "matrix"] },
+    "49": { topicTags: ["array", "hash-table", "string", "sorting"] },
+    "50": { topicTags: ["recursion", "math"] },
+    "51": { topicTags: ["array", "backtracking"] },
+    "52": { topicTags: ["backtracking"] },
+    "53": { topicTags: ["array", "divide-and-conquer", "dynamic-programming"] },
+    "54": { topicTags: ["array", "matrix", "simulation"] },
+    "55": { topicTags: ["greedy", "array", "dynamic-programming"] },
+    "56": { topicTags: ["array", "sorting"] },
+    "57": { topicTags: ["array"] },
+    "58": { topicTags: ["string"] },
+    "59": { topicTags: ["array", "matrix", "simulation"] },
+    "60": { topicTags: ["recursion", "math"] },
+    "61": { topicTags: ["linked-list", "two-pointers"] },
+    "62": { topicTags: ["math", "dynamic-programming", "combinatorics"] },
+    "63": { topicTags: ["array", "dynamic-programming", "matrix"] },
+    "64": { topicTags: ["array", "dynamic-programming", "matrix"] },
+    "65": { topicTags: ["string"] },
+    "66": { topicTags: ["array", "math"] },
+    "67": { topicTags: ["bit-manipulation", "math", "string", "simulation"] },
+    "68": { topicTags: ["array", "string", "simulation"] },
+    "69": { topicTags: ["math", "binary-search"] },
+    "70": { topicTags: ["memoization", "math", "dynamic-programming"] },
+    "71": { topicTags: ["stack", "string"] },
+    "72": { topicTags: ["string", "dynamic-programming"] },
+    "73": { topicTags: ["array", "hash-table", "matrix"] },
+    "74": { topicTags: ["array", "binary-search", "matrix"] },
+    "75": { topicTags: ["array", "two-pointers", "sorting"] },
+    "76": { topicTags: ["hash-table", "string", "sliding-window"] },
+    "77": { topicTags: ["backtracking"] },
+    "78": { topicTags: ["bit-manipulation", "array", "backtracking"] },
+    "79": { topicTags: ["array", "backtracking", "matrix"] },
+    "80": { topicTags: ["array", "two-pointers"] },
+    "81": { topicTags: ["array", "binary-search"] },
+    "82": { topicTags: ["linked-list", "two-pointers"] },
+    "83": { topicTags: ["linked-list"] },
+    "84": { topicTags: ["stack", "array", "monotonic-stack"] },
+    "85": {
+      topicTags: ["stack", "array", "dynamic-programming", "matrix", "monotonic-stack"],
+    },
+    "86": { topicTags: ["linked-list", "two-pointers"] },
+    "87": { topicTags: ["string", "dynamic-programming"] },
+    "88": { topicTags: ["array", "two-pointers", "sorting"] },
+    "89": { topicTags: ["bit-manipulation", "math", "backtracking"] },
+    "90": { topicTags: ["bit-manipulation", "array", "backtracking"] },
+    "91": { topicTags: ["string", "dynamic-programming"] },
+    "92": { topicTags: ["linked-list"] },
+    "93": { topicTags: ["string", "backtracking"] },
+    "94": { topicTags: ["stack", "tree", "depth-first-search", "binary-tree"] },
+    "95": {
+      topicTags: ["tree", "binary-search-tree", "dynamic-programming", "backtracking", "binary-tree"],
+    },
+    "96": {
+      topicTags: ["tree", "binary-search-tree", "math", "dynamic-programming", "binary-tree"],
+    },
+    "97": { topicTags: ["string", "dynamic-programming"] },
+    "98": {
+      topicTags: ["tree", "depth-first-search", "binary-search-tree", "binary-tree"],
+    },
+    "99": {
+      topicTags: ["tree", "depth-first-search", "binary-search-tree", "binary-tree"],
+    },
+    "100": {
+      topicTags: ["tree", "depth-first-search", "breadth-first-search", "binary-tree"],
+    },
+    "101": {
+      topicTags: ["tree", "depth-first-search", "breadth-first-search", "binary-tree"],
+    },
+    "102": { topicTags: ["tree", "breadth-first-search", "binary-tree"] },
+    "103": { topicTags: ["tree", "breadth-first-search", "binary-tree"] },
+    "104": {
+      topicTags: ["tree", "depth-first-search", "breadth-first-search", "binary-tree"],
+    },
+    "105": {
+      topicTags: ["tree", "array", "hash-table", "divide-and-conquer", "binary-tree"],
+    },
+    "106": {
+      topicTags: ["tree", "array", "hash-table", "divide-and-conquer", "binary-tree"],
+    },
+    "107": { topicTags: ["tree", "breadth-first-search", "binary-tree"] },
+    "108": {
+      topicTags: ["tree", "binary-search-tree", "array", "divide-and-conquer", "binary-tree"],
+    },
+    "109": {
+      topicTags: ["tree", "binary-search-tree", "linked-list", "divide-and-conquer", "binary-tree"],
+    },
+    "110": { topicTags: ["tree", "depth-first-search", "binary-tree"] },
+    "111": {
+      topicTags: ["tree", "depth-first-search", "breadth-first-search", "binary-tree"],
+    },
+    "112": {
+      topicTags: ["tree", "depth-first-search", "breadth-first-search", "binary-tree"],
+    },
+    "113": {
+      topicTags: ["tree", "depth-first-search", "backtracking", "binary-tree"],
+    },
+    "114": {
+      topicTags: ["stack", "tree", "depth-first-search", "linked-list", "binary-tree"],
+    },
+    "115": { topicTags: ["string", "dynamic-programming"] },
+    "116": {
+      topicTags: ["tree", "depth-first-search", "breadth-first-search", "linked-list", "binary-tree"],
+    },
+    "117": {
+      topicTags: ["tree", "depth-first-search", "breadth-first-search", "linked-list", "binary-tree"],
+    },
+    "118": { topicTags: ["array", "dynamic-programming"] },
+    "119": { topicTags: ["array", "dynamic-programming"] },
+    "120": { topicTags: ["array", "dynamic-programming"] },
+    "121": { topicTags: ["array", "dynamic-programming"] },
+    "122": { topicTags: ["greedy", "array", "dynamic-programming"] },
+    "123": { topicTags: ["array", "dynamic-programming"] },
+    "124": {
+      topicTags: ["tree", "depth-first-search", "dynamic-programming", "binary-tree"],
+    },
+    "125": { topicTags: ["two-pointers", "string"] },
+    "126": {
+      topicTags: ["breadth-first-search", "hash-table", "string", "backtracking"],
+    },
+    "127": { topicTags: ["breadth-first-search", "hash-table", "string"] },
+    "128": { topicTags: ["union-find", "array", "hash-table"] },
+    "129": { topicTags: ["tree", "depth-first-search", "binary-tree"] },
+    "130": {
+      topicTags: ["depth-first-search", "breadth-first-search", "union-find", "array", "matrix"],
+    },
+    "131": { topicTags: ["string", "dynamic-programming", "backtracking"] },
+    "132": { topicTags: ["string", "dynamic-programming"] },
+    "133": {
+      topicTags: ["depth-first-search", "breadth-first-search", "graph", "hash-table"],
+    },
+    "134": { topicTags: ["greedy", "array"] },
+    "135": { topicTags: ["greedy", "array"] },
+    "136": { topicTags: ["bit-manipulation", "array"] },
+    "137": { topicTags: ["bit-manipulation", "array"] },
+    "138": { topicTags: ["hash-table", "linked-list"] },
+    "139": {
+      topicTags: ["trie", "memoization", "hash-table", "string", "dynamic-programming"],
+    },
+    "140": {
+      topicTags: ["trie", "memoization", "hash-table", "string", "dynamic-programming", "backtracking"],
+    },
+    "141": { topicTags: ["hash-table", "linked-list", "two-pointers"] },
+    "142": { topicTags: ["hash-table", "linked-list", "two-pointers"] },
+    "143": { topicTags: ["stack", "recursion", "linked-list", "two-pointers"] },
+    "144": {
+      topicTags: ["stack", "tree", "depth-first-search", "binary-tree"],
+    },
+    "145": {
+      topicTags: ["stack", "tree", "depth-first-search", "binary-tree"],
+    },
+    "146": {
+      topicTags: ["design", "hash-table", "linked-list", "doubly-linked-list"],
+    },
+    "147": { topicTags: ["linked-list", "sorting"] },
+    "148": {
+      topicTags: ["linked-list", "two-pointers", "divide-and-conquer", "sorting", "merge-sort"],
+    },
+    "149": { topicTags: ["geometry", "array", "hash-table", "math"] },
+    "150": { topicTags: ["stack", "array", "math"] },
+    "151": { topicTags: ["two-pointers", "string"] },
+    "152": { topicTags: ["array", "dynamic-programming"] },
+    "153": { topicTags: ["array", "binary-search"] },
+    "154": { topicTags: ["array", "binary-search"] },
+    "155": { topicTags: ["stack", "design"] },
+    "156": { topicTags: ["tree", "depth-first-search", "binary-tree"] },
+    "157": { topicTags: ["string", "interactive", "simulation"] },
+    "158": { topicTags: ["string", "interactive", "simulation"] },
+    "159": { topicTags: ["hash-table", "string", "sliding-window"] },
+    "160": { topicTags: ["hash-table", "linked-list", "two-pointers"] },
+    "161": { topicTags: ["two-pointers", "string"] },
+    "162": { topicTags: ["array", "binary-search"] },
+    "163": { topicTags: ["array"] },
+    "164": { topicTags: ["array", "bucket-sort", "radix-sort", "sorting"] },
+    "165": { topicTags: ["two-pointers", "string"] },
+    "166": { topicTags: ["hash-table", "math", "string"] },
+    "167": { topicTags: ["array", "two-pointers", "binary-search"] },
+    "168": { topicTags: ["math", "string"] },
+    "169": {
+      topicTags: ["array", "hash-table", "divide-and-conquer", "counting", "sorting"],
+    },
+    "170": {
+      topicTags: ["design", "array", "hash-table", "two-pointers", "data-stream"],
+    },
+    "171": { topicTags: ["math", "string"] },
+    "172": { topicTags: ["math"] },
+    "173": {
+      topicTags: ["stack", "tree", "design", "binary-search-tree", "binary-tree", "iterator"],
+    },
+    "174": { topicTags: ["array", "dynamic-programming", "matrix"] },
+    "175": { topicTags: ["database"] },
+    "176": { topicTags: ["database"] },
+    "177": { topicTags: ["database"] },
+    "178": { topicTags: ["database"] },
+    "179": { topicTags: ["greedy", "string", "sorting"] },
+    "180": { topicTags: ["database"] },
+    "181": { topicTags: ["database"] },
+    "182": { topicTags: ["database"] },
+    "183": { topicTags: ["database"] },
+    "184": { topicTags: ["database"] },
+    "185": { topicTags: ["database"] },
+    "186": { topicTags: ["two-pointers", "string"] },
+    "187": {
+      topicTags: ["bit-manipulation", "hash-table", "string", "sliding-window", "hash-function", "rolling-hash"],
+    },
+    "188": { topicTags: ["array", "dynamic-programming"] },
+    "189": { topicTags: ["array", "math", "two-pointers"] },
+    "190": { topicTags: ["bit-manipulation", "divide-and-conquer"] },
+    "191": { topicTags: ["bit-manipulation", "divide-and-conquer"] },
+    "192": { topicTags: ["shell"] },
+    "193": { topicTags: ["shell"] },
+    "194": { topicTags: ["shell"] },
+    "195": { topicTags: ["shell"] },
+    "196": { topicTags: ["database"] },
+    "197": { topicTags: ["database"] },
+    "198": { topicTags: ["array", "dynamic-programming"] },
+    "199": {
+      topicTags: ["tree", "depth-first-search", "breadth-first-search", "binary-tree"],
+    },
+    "200": {
+      topicTags: ["depth-first-search", "breadth-first-search", "union-find", "array", "matrix"],
+    },
+    "201": { topicTags: ["bit-manipulation"] },
+    "202": { topicTags: ["hash-table", "math", "two-pointers"] },
+    "203": { topicTags: ["recursion", "linked-list"] },
+    "204": { topicTags: ["array", "math", "enumeration", "number-theory"] },
+    "205": { topicTags: ["hash-table", "string"] },
+    "206": { topicTags: ["recursion", "linked-list"] },
+    "207": {
+      topicTags: ["depth-first-search", "breadth-first-search", "graph", "topological-sort"],
+    },
+    "208": { topicTags: ["design", "trie", "hash-table", "string"] },
+    "209": {
+      topicTags: ["array", "binary-search", "prefix-sum", "sliding-window"],
+    },
+    "210": {
+      topicTags: ["depth-first-search", "breadth-first-search", "graph", "topological-sort"],
+    },
+    "211": { topicTags: ["depth-first-search", "design", "trie", "string"] },
+    "212": { topicTags: ["trie", "array", "string", "backtracking", "matrix"] },
+    "213": { topicTags: ["array", "dynamic-programming"] },
+    "214": {
+      topicTags: ["string", "string-matching", "hash-function", "rolling-hash"],
+    },
+    "215": {
+      topicTags: ["array", "divide-and-conquer", "quickselect", "sorting", "heap-priority-queue"],
+    },
+    "216": { topicTags: ["array", "backtracking"] },
+    "217": { topicTags: ["array", "hash-table", "sorting"] },
+    "218": {
+      topicTags: [
+        "binary-indexed-tree",
+        "segment-tree",
+        "array",
+        "divide-and-conquer",
+        "ordered-set",
+        "line-sweep",
+        "heap-priority-queue",
+      ],
+    },
+    "219": { topicTags: ["array", "hash-table", "sliding-window"] },
+    "220": {
+      topicTags: ["array", "bucket-sort", "ordered-set", "sorting", "sliding-window"],
+    },
+    "221": { topicTags: ["array", "dynamic-programming", "matrix"] },
+    "222": {
+      topicTags: ["tree", "depth-first-search", "binary-search", "binary-tree"],
+    },
+    "223": { topicTags: ["geometry", "math"] },
+    "224": { topicTags: ["stack", "recursion", "math", "string"] },
+    "225": { topicTags: ["stack", "design", "queue"] },
+    "226": {
+      topicTags: ["tree", "depth-first-search", "breadth-first-search", "binary-tree"],
+    },
+    "227": { topicTags: ["stack", "math", "string"] },
+    "228": { topicTags: ["array"] },
+    "229": { topicTags: ["array", "hash-table", "counting", "sorting"] },
+    "230": {
+      topicTags: ["tree", "depth-first-search", "binary-search-tree", "binary-tree"],
+    },
+    "231": { topicTags: ["bit-manipulation", "recursion", "math"] },
+    "232": { topicTags: ["stack", "design", "queue"] },
+    "233": { topicTags: ["recursion", "math", "dynamic-programming"] },
+    "234": { topicTags: ["stack", "recursion", "linked-list", "two-pointers"] },
+    "235": {
+      topicTags: ["tree", "depth-first-search", "binary-search-tree", "binary-tree"],
+    },
+    "236": { topicTags: ["tree", "depth-first-search", "binary-tree"] },
+    "237": { topicTags: ["linked-list"] },
+    "238": { topicTags: ["array", "prefix-sum"] },
+    "239": {
+      topicTags: ["queue", "array", "sliding-window", "monotonic-queue", "heap-priority-queue"],
+    },
+    "240": {
+      topicTags: ["array", "binary-search", "divide-and-conquer", "matrix"],
+    },
+    "241": {
+      topicTags: ["recursion", "memoization", "math", "string", "dynamic-programming"],
+    },
+    "242": { topicTags: ["hash-table", "string", "sorting"] },
+    "243": { topicTags: ["array", "string"] },
+    "244": {
+      topicTags: ["design", "array", "hash-table", "two-pointers", "string"],
+    },
+    "245": { topicTags: ["array", "string"] },
+    "246": { topicTags: ["hash-table", "two-pointers", "string"] },
+    "247": { topicTags: ["recursion", "array", "string"] },
+    "248": { topicTags: ["recursion", "array", "string"] },
+    "249": { topicTags: ["array", "hash-table", "string"] },
+    "250": { topicTags: ["tree", "depth-first-search", "binary-tree"] },
+    "251": { topicTags: ["design", "array", "two-pointers", "iterator"] },
+    "252": { topicTags: ["array", "sorting"] },
+    "253": {
+      topicTags: ["greedy", "array", "two-pointers", "prefix-sum", "sorting", "heap-priority-queue"],
+    },
+    "254": { topicTags: ["array", "backtracking"] },
+    "255": {
+      topicTags: ["stack", "tree", "binary-search-tree", "recursion", "binary-tree", "monotonic-stack"],
+    },
+    "256": { topicTags: ["array", "dynamic-programming"] },
+    "257": {
+      topicTags: ["tree", "depth-first-search", "string", "backtracking", "binary-tree"],
+    },
+    "258": { topicTags: ["math", "number-theory", "simulation"] },
+    "259": { topicTags: ["array", "two-pointers", "binary-search", "sorting"] },
+    "260": { topicTags: ["bit-manipulation", "array"] },
+    "261": {
+      topicTags: ["depth-first-search", "breadth-first-search", "union-find", "graph"],
+    },
+    "262": { topicTags: ["database"] },
+    "263": { topicTags: ["math"] },
+    "264": {
+      topicTags: ["hash-table", "math", "dynamic-programming", "heap-priority-queue"],
+    },
+    "265": { topicTags: ["array", "dynamic-programming"] },
+    "266": { topicTags: ["bit-manipulation", "hash-table", "string"] },
+    "267": { topicTags: ["hash-table", "string", "backtracking"] },
+    "268": {
+      topicTags: ["bit-manipulation", "array", "hash-table", "math", "binary-search", "sorting"],
+    },
+    "269": {
+      topicTags: ["depth-first-search", "breadth-first-search", "graph", "topological-sort", "array", "string"],
+    },
+    "270": {
+      topicTags: ["tree", "depth-first-search", "binary-search-tree", "binary-search", "binary-tree"],
+    },
+    "271": { topicTags: ["design", "array", "string"] },
+    "272": {
+      topicTags: [
+        "stack",
+        "tree",
+        "depth-first-search",
+        "binary-search-tree",
+        "two-pointers",
+        "binary-tree",
+        "heap-priority-queue",
+      ],
+    },
+    "273": { topicTags: ["recursion", "math", "string"] },
+    "274": { topicTags: ["array", "counting-sort", "sorting"] },
+    "275": { topicTags: ["array", "binary-search"] },
+    "276": { topicTags: ["dynamic-programming"] },
+    "277": { topicTags: ["greedy", "graph", "two-pointers", "interactive"] },
+    "278": { topicTags: ["binary-search", "interactive"] },
+    "279": {
+      topicTags: ["breadth-first-search", "math", "dynamic-programming"],
+    },
+    "280": { topicTags: ["greedy", "array", "sorting"] },
+    "281": { topicTags: ["design", "queue", "array", "iterator"] },
+    "282": { topicTags: ["math", "string", "backtracking"] },
+    "283": { topicTags: ["array", "two-pointers"] },
+    "284": { topicTags: ["design", "array", "iterator"] },
+    "285": {
+      topicTags: ["tree", "depth-first-search", "binary-search-tree", "binary-tree"],
+    },
+    "286": { topicTags: ["breadth-first-search", "array", "matrix"] },
+    "287": {
+      topicTags: ["bit-manipulation", "array", "two-pointers", "binary-search"],
+    },
+    "288": { topicTags: ["design", "array", "hash-table", "string"] },
+    "289": { topicTags: ["array", "matrix", "simulation"] },
+    "290": { topicTags: ["hash-table", "string"] },
+    "291": { topicTags: ["hash-table", "string", "backtracking"] },
+    "292": { topicTags: ["brainteaser", "math", "game-theory"] },
+    "293": { topicTags: ["string"] },
+    "294": {
+      topicTags: ["memoization", "math", "dynamic-programming", "backtracking", "game-theory"],
+    },
+    "295": {
+      topicTags: ["design", "two-pointers", "data-stream", "sorting", "heap-priority-queue"],
+    },
+    "296": { topicTags: ["array", "math", "matrix", "sorting"] },
+    "297": {
+      topicTags: ["tree", "depth-first-search", "breadth-first-search", "design", "string", "binary-tree"],
+    },
+    "298": { topicTags: ["tree", "depth-first-search", "binary-tree"] },
+    "299": { topicTags: ["hash-table", "string", "counting"] },
+    "300": { topicTags: ["array", "binary-search", "dynamic-programming"] },
+    "301": { topicTags: ["breadth-first-search", "string", "backtracking"] },
+    "302": {
+      topicTags: ["depth-first-search", "breadth-first-search", "array", "binary-search", "matrix"],
+    },
+    "303": { topicTags: ["design", "array", "prefix-sum"] },
+    "304": { topicTags: ["design", "array", "matrix", "prefix-sum"] },
+    "305": { topicTags: ["union-find", "array"] },
+    "306": { topicTags: ["string", "backtracking"] },
+    "307": {
+      topicTags: ["design", "binary-indexed-tree", "segment-tree", "array"],
+    },
+    "308": {
+      topicTags: ["design", "binary-indexed-tree", "segment-tree", "array", "matrix"],
+    },
+    "309": { topicTags: ["array", "dynamic-programming"] },
+    "310": {
+      topicTags: ["depth-first-search", "breadth-first-search", "graph", "topological-sort"],
+    },
+    "311": { topicTags: ["array", "hash-table", "matrix"] },
+    "312": { topicTags: ["array", "dynamic-programming"] },
+    "313": { topicTags: ["array", "math", "dynamic-programming"] },
+    "314": {
+      topicTags: ["tree", "depth-first-search", "breadth-first-search", "hash-table", "binary-tree"],
+    },
+    "315": {
+      topicTags: [
+        "binary-indexed-tree",
+        "segment-tree",
+        "array",
+        "binary-search",
+        "divide-and-conquer",
+        "ordered-set",
+        "merge-sort",
+      ],
+    },
+    "316": { topicTags: ["stack", "greedy", "string", "monotonic-stack"] },
+    "317": { topicTags: ["breadth-first-search", "array", "matrix"] },
+    "318": { topicTags: ["bit-manipulation", "array", "string"] },
+    "319": { topicTags: ["brainteaser", "math"] },
+    "320": { topicTags: ["bit-manipulation", "string", "backtracking"] },
+    "321": { topicTags: ["stack", "greedy", "monotonic-stack"] },
+    "322": {
+      topicTags: ["breadth-first-search", "array", "dynamic-programming"],
+    },
+    "323": {
+      topicTags: ["depth-first-search", "breadth-first-search", "union-find", "graph"],
+    },
+    "324": {
+      topicTags: ["array", "divide-and-conquer", "quickselect", "sorting"],
+    },
+    "325": { topicTags: ["array", "hash-table"] },
+    "326": { topicTags: ["recursion", "math"] },
+    "327": {
+      topicTags: [
+        "binary-indexed-tree",
+        "segment-tree",
+        "array",
+        "binary-search",
+        "divide-and-conquer",
+        "ordered-set",
+        "merge-sort",
+      ],
+    },
+    "328": { topicTags: ["linked-list"] },
+    "329": {
+      topicTags: [
+        "depth-first-search",
+        "breadth-first-search",
+        "graph",
+        "topological-sort",
+        "memoization",
+        "array",
+        "dynamic-programming",
+        "matrix",
+      ],
+    },
+    "330": { topicTags: ["greedy", "array"] },
+    "331": { topicTags: ["stack", "tree", "string", "binary-tree"] },
+    "332": { topicTags: ["depth-first-search", "graph", "eulerian-circuit"] },
+    "333": {
+      topicTags: ["tree", "depth-first-search", "binary-search-tree", "dynamic-programming", "binary-tree"],
+    },
+    "334": { topicTags: ["greedy", "array"] },
+    "335": { topicTags: ["geometry", "array", "math"] },
+    "336": { topicTags: ["trie", "array", "hash-table", "string"] },
+    "337": {
+      topicTags: ["tree", "depth-first-search", "dynamic-programming", "binary-tree"],
+    },
+    "338": { topicTags: ["bit-manipulation", "dynamic-programming"] },
+    "339": { topicTags: ["depth-first-search", "breadth-first-search"] },
+    "340": { topicTags: ["hash-table", "string", "sliding-window"] },
+    "341": {
+      topicTags: ["stack", "tree", "depth-first-search", "design", "queue", "iterator"],
+    },
+    "342": { topicTags: ["bit-manipulation", "recursion", "math"] },
+    "343": { topicTags: ["math", "dynamic-programming"] },
+    "344": { topicTags: ["recursion", "two-pointers", "string"] },
+    "345": { topicTags: ["two-pointers", "string"] },
+    "346": { topicTags: ["design", "queue", "array", "data-stream"] },
+    "347": {
+      topicTags: [
+        "array",
+        "hash-table",
+        "divide-and-conquer",
+        "bucket-sort",
+        "counting",
+        "quickselect",
+        "sorting",
+        "heap-priority-queue",
+      ],
+    },
+    "348": { topicTags: ["design", "array", "hash-table", "matrix"] },
+    "349": {
+      topicTags: ["array", "hash-table", "two-pointers", "binary-search", "sorting"],
+    },
+    "350": {
+      topicTags: ["array", "hash-table", "two-pointers", "binary-search", "sorting"],
+    },
+    "351": { topicTags: ["dynamic-programming", "backtracking"] },
+    "352": { topicTags: ["design", "binary-search", "ordered-set"] },
+    "353": { topicTags: ["design", "queue", "array", "matrix"] },
+    "354": {
+      topicTags: ["array", "binary-search", "dynamic-programming", "sorting"],
+    },
+    "355": {
+      topicTags: ["design", "hash-table", "linked-list", "heap-priority-queue"],
+    },
+    "356": { topicTags: ["array", "hash-table", "math"] },
+    "357": { topicTags: ["math", "dynamic-programming", "backtracking"] },
+    "358": {
+      topicTags: ["greedy", "hash-table", "string", "counting", "sorting", "heap-priority-queue"],
+    },
+    "359": { topicTags: ["design", "hash-table"] },
+    "360": { topicTags: ["array", "math", "two-pointers", "sorting"] },
+    "361": { topicTags: ["array", "dynamic-programming", "matrix"] },
+    "362": {
+      topicTags: ["design", "queue", "array", "hash-table", "binary-search"],
+    },
+    "363": {
+      topicTags: ["array", "binary-search", "matrix", "ordered-set", "prefix-sum"],
+    },
+    "364": {
+      topicTags: ["stack", "depth-first-search", "breadth-first-search"],
+    },
+    "365": {
+      topicTags: ["depth-first-search", "breadth-first-search", "math"],
+    },
+    "366": { topicTags: ["tree", "depth-first-search", "binary-tree"] },
+    "367": { topicTags: ["math", "binary-search"] },
+    "368": { topicTags: ["array", "math", "dynamic-programming", "sorting"] },
+    "369": { topicTags: ["linked-list", "math"] },
+    "370": { topicTags: ["array", "prefix-sum"] },
+    "371": { topicTags: ["bit-manipulation", "math"] },
+    "372": { topicTags: ["math", "divide-and-conquer"] },
+    "373": { topicTags: ["array", "heap-priority-queue"] },
+    "374": { topicTags: ["binary-search", "interactive"] },
+    "375": { topicTags: ["math", "dynamic-programming", "game-theory"] },
+    "376": { topicTags: ["greedy", "array", "dynamic-programming"] },
+    "377": { topicTags: ["array", "dynamic-programming"] },
+    "378": {
+      topicTags: ["array", "binary-search", "matrix", "sorting", "heap-priority-queue"],
+    },
+    "379": {
+      topicTags: ["design", "queue", "array", "hash-table", "linked-list"],
+    },
+    "380": {
+      topicTags: ["design", "array", "hash-table", "math", "randomized"],
+    },
+    "381": {
+      topicTags: ["design", "array", "hash-table", "math", "randomized"],
+    },
+    "382": {
+      topicTags: ["reservoir-sampling", "linked-list", "math", "randomized"],
+    },
+    "383": { topicTags: ["hash-table", "string", "counting"] },
+    "384": { topicTags: ["array", "math", "randomized"] },
+    "385": { topicTags: ["stack", "depth-first-search", "string"] },
+    "386": { topicTags: ["depth-first-search", "trie"] },
+    "387": { topicTags: ["queue", "hash-table", "string", "counting"] },
+    "388": { topicTags: ["stack", "depth-first-search", "string"] },
+    "389": {
+      topicTags: ["bit-manipulation", "hash-table", "string", "sorting"],
+    },
+    "390": { topicTags: ["recursion", "math"] },
+    "391": { topicTags: ["array", "line-sweep"] },
+    "392": { topicTags: ["two-pointers", "string", "dynamic-programming"] },
+    "393": { topicTags: ["bit-manipulation", "array"] },
+    "394": { topicTags: ["stack", "recursion", "string"] },
+    "395": {
+      topicTags: ["hash-table", "string", "divide-and-conquer", "sliding-window"],
+    },
+    "396": { topicTags: ["array", "math", "dynamic-programming"] },
+    "397": {
+      topicTags: ["greedy", "bit-manipulation", "memoization", "dynamic-programming"],
+    },
+    "398": {
+      topicTags: ["reservoir-sampling", "hash-table", "math", "randomized"],
+    },
+    "399": {
+      topicTags: ["depth-first-search", "breadth-first-search", "union-find", "graph", "array", "shortest-path"],
+    },
+    "400": { topicTags: ["math", "binary-search"] },
+    "401": { topicTags: ["bit-manipulation", "backtracking"] },
+    "402": { topicTags: ["stack", "greedy", "string", "monotonic-stack"] },
+    "403": { topicTags: ["array", "dynamic-programming"] },
+    "404": {
+      topicTags: ["tree", "depth-first-search", "breadth-first-search", "binary-tree"],
+    },
+    "405": { topicTags: ["bit-manipulation", "math"] },
+    "406": {
+      topicTags: ["greedy", "binary-indexed-tree", "segment-tree", "array", "sorting"],
+    },
+    "407": {
+      topicTags: ["breadth-first-search", "array", "matrix", "heap-priority-queue"],
+    },
+    "408": { topicTags: ["two-pointers", "string"] },
+    "409": { topicTags: ["greedy", "hash-table", "string"] },
+    "410": {
+      topicTags: ["greedy", "array", "binary-search", "dynamic-programming"],
+    },
+    "411": { topicTags: ["bit-manipulation", "string", "backtracking"] },
+    "412": { topicTags: ["math", "string", "simulation"] },
+    "413": { topicTags: ["array", "dynamic-programming"] },
+    "414": { topicTags: ["array", "sorting"] },
+    "415": { topicTags: ["math", "string", "simulation"] },
+    "416": { topicTags: ["array", "dynamic-programming"] },
+    "417": {
+      topicTags: ["depth-first-search", "breadth-first-search", "array", "matrix"],
+    },
+    "418": { topicTags: ["string", "dynamic-programming", "simulation"] },
+    "419": { topicTags: ["depth-first-search", "array", "matrix"] },
+    "420": { topicTags: ["greedy", "string", "heap-priority-queue"] },
+    "421": { topicTags: ["bit-manipulation", "trie", "array", "hash-table"] },
+    "422": { topicTags: ["array", "matrix"] },
+    "423": { topicTags: ["hash-table", "math", "string"] },
+    "424": { topicTags: ["hash-table", "string", "sliding-window"] },
+    "425": { topicTags: ["trie", "array", "string", "backtracking"] },
+    "426": {
+      topicTags: [
+        "stack",
+        "tree",
+        "depth-first-search",
+        "binary-search-tree",
+        "linked-list",
+        "binary-tree",
+        "doubly-linked-list",
+      ],
+    },
+    "427": { topicTags: ["tree", "array", "divide-and-conquer", "matrix"] },
+    "428": {
+      topicTags: ["tree", "depth-first-search", "breadth-first-search", "string"],
+    },
+    "429": { topicTags: ["tree", "breadth-first-search"] },
+    "430": {
+      topicTags: ["depth-first-search", "linked-list", "doubly-linked-list"],
+    },
+    "431": {
+      topicTags: ["tree", "depth-first-search", "breadth-first-search", "design", "binary-tree"],
+    },
+    "432": {
+      topicTags: ["design", "hash-table", "linked-list", "doubly-linked-list"],
+    },
+    "433": { topicTags: ["breadth-first-search", "hash-table", "string"] },
+    "434": { topicTags: ["string"] },
+    "435": { topicTags: ["greedy", "array", "dynamic-programming", "sorting"] },
+    "436": { topicTags: ["array", "binary-search", "sorting"] },
+    "437": { topicTags: ["tree", "depth-first-search", "binary-tree"] },
+    "438": { topicTags: ["hash-table", "string", "sliding-window"] },
+    "439": { topicTags: ["stack", "recursion", "string"] },
+    "440": { topicTags: ["trie"] },
+    "441": { topicTags: ["math", "binary-search"] },
+    "442": { topicTags: ["array", "hash-table"] },
+    "443": { topicTags: ["two-pointers", "string"] },
+    "444": { topicTags: ["graph", "topological-sort", "array"] },
+    "445": { topicTags: ["stack", "linked-list", "math"] },
+    "446": { topicTags: ["array", "dynamic-programming"] },
+    "447": { topicTags: ["array", "hash-table", "math"] },
+    "448": { topicTags: ["array", "hash-table"] },
+    "449": {
+      topicTags: [
+        "tree",
+        "depth-first-search",
+        "breadth-first-search",
+        "design",
+        "binary-search-tree",
+        "string",
+        "binary-tree",
+      ],
+    },
+    "450": { topicTags: ["tree", "binary-search-tree", "binary-tree"] },
+    "451": {
+      topicTags: ["hash-table", "string", "bucket-sort", "counting", "sorting", "heap-priority-queue"],
+    },
+    "452": { topicTags: ["greedy", "array", "sorting"] },
+    "453": { topicTags: ["array", "math"] },
+    "454": { topicTags: ["array", "hash-table"] },
+    "455": { topicTags: ["greedy", "array", "two-pointers", "sorting"] },
+    "456": {
+      topicTags: ["stack", "array", "binary-search", "ordered-set", "monotonic-stack"],
+    },
+    "457": { topicTags: ["array", "hash-table", "two-pointers"] },
+    "458": { topicTags: ["math", "dynamic-programming", "combinatorics"] },
+    "459": { topicTags: ["string", "string-matching"] },
+    "460": {
+      topicTags: ["design", "hash-table", "linked-list", "doubly-linked-list"],
+    },
+    "461": { topicTags: ["bit-manipulation"] },
+    "462": { topicTags: ["array", "math", "sorting"] },
+    "463": {
+      topicTags: ["depth-first-search", "breadth-first-search", "array", "matrix"],
+    },
+    "464": {
+      topicTags: ["bit-manipulation", "memoization", "math", "dynamic-programming", "bitmask", "game-theory"],
+    },
+    "465": {
+      topicTags: ["bit-manipulation", "array", "dynamic-programming", "backtracking", "bitmask"],
+    },
+    "466": { topicTags: ["string", "dynamic-programming"] },
+    "467": { topicTags: ["string", "dynamic-programming"] },
+    "468": { topicTags: ["string"] },
+    "469": { topicTags: ["geometry", "math"] },
+    "470": {
+      topicTags: ["math", "rejection-sampling", "probability-and-statistics", "randomized"],
+    },
+    "471": { topicTags: ["string", "dynamic-programming"] },
+    "472": {
+      topicTags: ["depth-first-search", "trie", "array", "string", "dynamic-programming"],
+    },
+    "473": {
+      topicTags: ["bit-manipulation", "array", "dynamic-programming", "backtracking", "bitmask"],
+    },
+    "474": { topicTags: ["array", "string", "dynamic-programming"] },
+    "475": { topicTags: ["array", "two-pointers", "binary-search", "sorting"] },
+    "476": { topicTags: ["bit-manipulation"] },
+    "477": { topicTags: ["bit-manipulation", "array", "math"] },
+    "478": {
+      topicTags: ["geometry", "math", "rejection-sampling", "randomized"],
+    },
+    "479": { topicTags: ["math"] },
+    "480": {
+      topicTags: ["array", "hash-table", "sliding-window", "heap-priority-queue"],
+    },
+    "481": { topicTags: ["two-pointers", "string"] },
+    "482": { topicTags: ["string"] },
+    "483": { topicTags: ["math", "binary-search"] },
+    "484": { topicTags: ["stack", "greedy", "array", "string"] },
+    "485": { topicTags: ["array"] },
+    "486": {
+      topicTags: ["recursion", "array", "math", "dynamic-programming", "game-theory"],
+    },
+    "487": { topicTags: ["array", "dynamic-programming", "sliding-window"] },
+    "488": {
+      topicTags: ["breadth-first-search", "memoization", "string", "dynamic-programming"],
+    },
+    "489": { topicTags: ["backtracking", "interactive"] },
+    "490": {
+      topicTags: ["depth-first-search", "breadth-first-search", "graph"],
+    },
+    "491": {
+      topicTags: ["bit-manipulation", "array", "hash-table", "backtracking"],
+    },
+    "492": { topicTags: ["math"] },
+    "493": {
+      topicTags: [
+        "binary-indexed-tree",
+        "segment-tree",
+        "array",
+        "binary-search",
+        "divide-and-conquer",
+        "ordered-set",
+        "merge-sort",
+      ],
+    },
+    "494": { topicTags: ["array", "dynamic-programming", "backtracking"] },
+    "495": { topicTags: ["array", "simulation"] },
+    "496": { topicTags: ["stack", "array", "hash-table", "monotonic-stack"] },
+    "497": {
+      topicTags: ["reservoir-sampling", "math", "binary-search", "ordered-set", "prefix-sum", "randomized"],
+    },
+    "498": { topicTags: ["array", "matrix", "simulation"] },
+    "499": {
+      topicTags: ["depth-first-search", "breadth-first-search", "graph", "shortest-path", "heap-priority-queue"],
+    },
+    "500": { topicTags: ["array", "hash-table", "string"] },
+    "501": {
+      topicTags: ["tree", "depth-first-search", "binary-search-tree", "binary-tree"],
+    },
+    "502": { topicTags: ["greedy", "array", "sorting", "heap-priority-queue"] },
+    "503": { topicTags: ["stack", "array", "monotonic-stack"] },
+    "504": { topicTags: ["math"] },
+    "505": {
+      topicTags: ["depth-first-search", "breadth-first-search", "graph", "shortest-path", "heap-priority-queue"],
+    },
+    "506": { topicTags: ["array", "sorting", "heap-priority-queue"] },
+    "507": { topicTags: ["math"] },
+    "508": {
+      topicTags: ["tree", "depth-first-search", "hash-table", "binary-tree"],
+    },
+    "509": {
+      topicTags: ["recursion", "memoization", "math", "dynamic-programming"],
+    },
+    "510": { topicTags: ["tree", "binary-search-tree", "binary-tree"] },
+    "511": { topicTags: ["database"] },
+    "512": { topicTags: ["database"] },
+    "513": {
+      topicTags: ["tree", "depth-first-search", "breadth-first-search", "binary-tree"],
+    },
+    "514": {
+      topicTags: ["depth-first-search", "breadth-first-search", "string", "dynamic-programming"],
+    },
+    "515": {
+      topicTags: ["tree", "depth-first-search", "breadth-first-search", "binary-tree"],
+    },
+    "516": { topicTags: ["string", "dynamic-programming"] },
+    "517": { topicTags: ["greedy", "array"] },
+    "518": { topicTags: ["array", "dynamic-programming"] },
+    "519": {
+      topicTags: ["reservoir-sampling", "hash-table", "math", "randomized"],
+    },
+    "520": { topicTags: ["string"] },
+    "521": { topicTags: ["string"] },
+    "522": {
+      topicTags: ["array", "hash-table", "two-pointers", "string", "sorting"],
+    },
+    "523": { topicTags: ["array", "hash-table", "math", "prefix-sum"] },
+    "524": { topicTags: ["array", "two-pointers", "string", "sorting"] },
+    "525": { topicTags: ["array", "hash-table", "prefix-sum"] },
+    "526": {
+      topicTags: ["bit-manipulation", "array", "dynamic-programming", "backtracking", "bitmask"],
+    },
+    "527": { topicTags: ["greedy", "trie", "array", "string", "sorting"] },
+    "528": { topicTags: ["math", "binary-search", "prefix-sum", "randomized"] },
+    "529": {
+      topicTags: ["depth-first-search", "breadth-first-search", "array", "matrix"],
+    },
+    "530": {
+      topicTags: ["tree", "depth-first-search", "breadth-first-search", "binary-search-tree", "binary-tree"],
+    },
+    "531": { topicTags: ["array", "hash-table", "matrix"] },
+    "532": {
+      topicTags: ["array", "hash-table", "two-pointers", "binary-search", "sorting"],
+    },
+    "533": { topicTags: ["array", "hash-table", "matrix"] },
+    "534": { topicTags: ["database"] },
+    "535": { topicTags: ["design", "hash-table", "string", "hash-function"] },
+    "536": {
+      topicTags: ["tree", "depth-first-search", "string", "binary-tree"],
+    },
+    "537": { topicTags: ["math", "string", "simulation"] },
+    "538": {
+      topicTags: ["tree", "depth-first-search", "binary-search-tree", "binary-tree"],
+    },
+    "539": { topicTags: ["array", "math", "string", "sorting"] },
+    "540": { topicTags: ["array", "binary-search"] },
+    "541": { topicTags: ["two-pointers", "string"] },
+    "542": {
+      topicTags: ["breadth-first-search", "array", "dynamic-programming", "matrix"],
+    },
+    "543": { topicTags: ["tree", "depth-first-search", "binary-tree"] },
+    "544": { topicTags: ["recursion", "string", "simulation"] },
+    "545": { topicTags: ["tree", "depth-first-search", "binary-tree"] },
+    "546": { topicTags: ["memoization", "array", "dynamic-programming"] },
+    "547": {
+      topicTags: ["depth-first-search", "breadth-first-search", "union-find", "graph"],
+    },
+    "548": { topicTags: ["array", "prefix-sum"] },
+    "549": { topicTags: ["tree", "depth-first-search", "binary-tree"] },
+    "550": { topicTags: ["database"] },
+    "551": { topicTags: ["string"] },
+    "552": { topicTags: ["dynamic-programming"] },
+    "553": { topicTags: ["array", "math", "dynamic-programming"] },
+    "554": { topicTags: ["array", "hash-table"] },
+    "555": { topicTags: ["greedy", "array", "string"] },
+    "556": { topicTags: ["math", "two-pointers", "string"] },
+    "557": { topicTags: ["two-pointers", "string"] },
+    "558": { topicTags: ["tree", "divide-and-conquer"] },
+    "559": {
+      topicTags: ["tree", "depth-first-search", "breadth-first-search"],
+    },
+    "560": { topicTags: ["array", "hash-table", "prefix-sum"] },
+    "561": { topicTags: ["greedy", "array", "counting-sort", "sorting"] },
+    "562": { topicTags: ["array", "dynamic-programming", "matrix"] },
+    "563": { topicTags: ["tree", "depth-first-search", "binary-tree"] },
+    "564": { topicTags: ["math", "string"] },
+    "565": { topicTags: ["depth-first-search", "array"] },
+    "566": { topicTags: ["array", "matrix", "simulation"] },
+    "567": {
+      topicTags: ["hash-table", "two-pointers", "string", "sliding-window"],
+    },
+    "568": { topicTags: ["array", "dynamic-programming", "matrix"] },
+    "569": { topicTags: ["database"] },
+    "570": { topicTags: ["database"] },
+    "571": { topicTags: ["database"] },
+    "572": {
+      topicTags: ["tree", "depth-first-search", "binary-tree", "string-matching", "hash-function"],
+    },
+    "573": { topicTags: ["array", "math"] },
+    "574": { topicTags: ["database"] },
+    "575": { topicTags: ["array", "hash-table"] },
+    "576": { topicTags: ["dynamic-programming"] },
+    "577": { topicTags: ["database"] },
+    "578": { topicTags: ["database"] },
+    "579": { topicTags: ["database"] },
+    "580": { topicTags: ["database"] },
+    "581": {
+      topicTags: ["stack", "greedy", "array", "two-pointers", "sorting", "monotonic-stack"],
+    },
+    "582": {
+      topicTags: ["tree", "depth-first-search", "breadth-first-search", "array", "hash-table"],
+    },
+    "583": { topicTags: ["string", "dynamic-programming"] },
+    "584": { topicTags: ["database"] },
+    "585": { topicTags: ["database"] },
+    "586": { topicTags: ["database"] },
+    "587": { topicTags: ["geometry", "array", "math"] },
+    "588": { topicTags: ["design", "trie", "hash-table", "string"] },
+    "589": { topicTags: ["stack", "tree", "depth-first-search"] },
+    "590": { topicTags: ["stack", "tree", "depth-first-search"] },
+    "591": { topicTags: ["stack", "string"] },
+    "592": { topicTags: ["math", "string", "simulation"] },
+    "593": { topicTags: ["geometry", "math"] },
+    "594": { topicTags: ["array", "hash-table", "sorting"] },
+    "595": { topicTags: ["database"] },
+    "596": { topicTags: ["database"] },
+    "597": { topicTags: ["database"] },
+    "598": { topicTags: ["array", "math"] },
+    "599": { topicTags: ["array", "hash-table", "string"] },
+    "600": { topicTags: ["dynamic-programming"] },
+    "601": { topicTags: ["database"] },
+    "602": { topicTags: ["database"] },
+    "603": { topicTags: ["database"] },
+    "604": {
+      topicTags: ["design", "array", "hash-table", "string", "iterator"],
+    },
+    "605": { topicTags: ["greedy", "array"] },
+    "606": {
+      topicTags: ["tree", "depth-first-search", "string", "binary-tree"],
+    },
+    "607": { topicTags: ["database"] },
+    "608": { topicTags: ["database"] },
+    "609": { topicTags: ["array", "hash-table", "string"] },
+    "610": { topicTags: ["database"] },
+    "611": {
+      topicTags: ["greedy", "array", "two-pointers", "binary-search", "sorting"],
+    },
+    "612": { topicTags: ["database"] },
+    "613": { topicTags: ["database"] },
+    "614": { topicTags: ["database"] },
+    "615": { topicTags: ["database"] },
+    "616": {
+      topicTags: ["trie", "array", "hash-table", "string", "string-matching"],
+    },
+    "617": {
+      topicTags: ["tree", "depth-first-search", "breadth-first-search", "binary-tree"],
+    },
+    "618": { topicTags: ["database"] },
+    "619": { topicTags: ["database"] },
+    "620": { topicTags: ["database"] },
+    "621": {
+      topicTags: ["greedy", "array", "hash-table", "counting", "sorting", "heap-priority-queue"],
+    },
+    "622": { topicTags: ["design", "queue", "array", "linked-list"] },
+    "623": {
+      topicTags: ["tree", "depth-first-search", "breadth-first-search", "binary-tree"],
+    },
+    "624": { topicTags: ["greedy", "array"] },
+    "625": { topicTags: ["greedy", "math"] },
+    "626": { topicTags: ["database"] },
+    "627": { topicTags: ["database"] },
+    "628": { topicTags: ["array", "math", "sorting"] },
+    "629": { topicTags: ["dynamic-programming"] },
+    "630": { topicTags: ["greedy", "array", "heap-priority-queue"] },
+    "631": { topicTags: ["graph", "design", "topological-sort"] },
+    "632": {
+      topicTags: ["greedy", "array", "hash-table", "sorting", "sliding-window", "heap-priority-queue"],
+    },
+    "633": { topicTags: ["math", "two-pointers", "binary-search"] },
+    "634": { topicTags: ["math", "dynamic-programming"] },
+    "635": { topicTags: ["design", "hash-table", "string", "ordered-set"] },
+    "636": { topicTags: ["stack", "array"] },
+    "637": {
+      topicTags: ["tree", "depth-first-search", "breadth-first-search", "binary-tree"],
+    },
+    "638": {
+      topicTags: ["bit-manipulation", "memoization", "array", "dynamic-programming", "backtracking", "bitmask"],
+    },
+    "639": { topicTags: ["string", "dynamic-programming"] },
+    "640": { topicTags: ["math", "string", "simulation"] },
+    "641": { topicTags: ["design", "queue", "array", "linked-list"] },
+    "642": { topicTags: ["design", "trie", "string", "data-stream"] },
+    "643": { topicTags: ["array", "sliding-window"] },
+    "644": { topicTags: ["array", "binary-search", "prefix-sum"] },
+    "645": {
+      topicTags: ["bit-manipulation", "array", "hash-table", "sorting"],
+    },
+    "646": { topicTags: ["greedy", "array", "dynamic-programming", "sorting"] },
+    "647": { topicTags: ["string", "dynamic-programming"] },
+    "648": { topicTags: ["trie", "array", "hash-table", "string"] },
+    "649": { topicTags: ["greedy", "queue", "string"] },
+    "650": { topicTags: ["math", "dynamic-programming"] },
+    "651": { topicTags: ["math", "dynamic-programming"] },
+    "652": {
+      topicTags: ["tree", "depth-first-search", "hash-table", "binary-tree"],
+    },
+    "653": {
+      topicTags: [
+        "tree",
+        "depth-first-search",
+        "breadth-first-search",
+        "binary-search-tree",
+        "hash-table",
+        "two-pointers",
+        "binary-tree",
+      ],
+    },
+    "654": {
+      topicTags: ["stack", "tree", "array", "divide-and-conquer", "binary-tree", "monotonic-stack"],
+    },
+    "655": {
+      topicTags: ["tree", "depth-first-search", "breadth-first-search", "binary-tree"],
+    },
+    "656": { topicTags: ["array", "dynamic-programming"] },
+    "657": { topicTags: ["string", "simulation"] },
+    "658": {
+      topicTags: ["array", "two-pointers", "binary-search", "sorting", "heap-priority-queue"],
+    },
+    "659": {
+      topicTags: ["greedy", "array", "hash-table", "heap-priority-queue"],
+    },
+    "660": { topicTags: ["math"] },
+    "661": { topicTags: ["array", "matrix"] },
+    "662": {
+      topicTags: ["tree", "depth-first-search", "breadth-first-search", "binary-tree"],
+    },
+    "663": { topicTags: ["tree", "depth-first-search", "binary-tree"] },
+    "664": { topicTags: ["string", "dynamic-programming"] },
+    "665": { topicTags: ["array"] },
+    "666": {
+      topicTags: ["tree", "depth-first-search", "array", "binary-tree"],
+    },
+    "667": { topicTags: ["array", "math"] },
+    "668": { topicTags: ["math", "binary-search"] },
+    "669": {
+      topicTags: ["tree", "depth-first-search", "binary-search-tree", "binary-tree"],
+    },
+    "670": { topicTags: ["greedy", "math"] },
+    "671": { topicTags: ["tree", "depth-first-search", "binary-tree"] },
+    "672": {
+      topicTags: ["bit-manipulation", "depth-first-search", "breadth-first-search", "math"],
+    },
+    "673": {
+      topicTags: ["binary-indexed-tree", "segment-tree", "array", "dynamic-programming"],
+    },
+    "674": { topicTags: ["array"] },
+    "675": {
+      topicTags: ["breadth-first-search", "array", "matrix", "heap-priority-queue"],
+    },
+    "676": { topicTags: ["design", "trie", "hash-table", "string"] },
+    "677": { topicTags: ["design", "trie", "hash-table", "string"] },
+    "678": { topicTags: ["stack", "greedy", "string", "dynamic-programming"] },
+    "679": { topicTags: ["array", "math", "backtracking"] },
+    "680": { topicTags: ["greedy", "two-pointers", "string"] },
+    "681": { topicTags: ["string", "enumeration"] },
+    "682": { topicTags: ["stack", "array", "simulation"] },
+    "683": {
+      topicTags: ["binary-indexed-tree", "array", "ordered-set", "sliding-window"],
+    },
+    "684": {
+      topicTags: ["depth-first-search", "breadth-first-search", "union-find", "graph"],
+    },
+    "685": {
+      topicTags: ["depth-first-search", "breadth-first-search", "union-find", "graph"],
+    },
+    "686": { topicTags: ["string", "string-matching"] },
+    "687": { topicTags: ["tree", "depth-first-search", "binary-tree"] },
+    "688": { topicTags: ["dynamic-programming"] },
+    "689": { topicTags: ["array", "dynamic-programming"] },
+    "690": {
+      topicTags: ["depth-first-search", "breadth-first-search", "hash-table"],
+    },
+    "691": {
+      topicTags: ["bit-manipulation", "array", "string", "dynamic-programming", "backtracking", "bitmask"],
+    },
+    "692": {
+      topicTags: ["trie", "hash-table", "string", "bucket-sort", "counting", "sorting", "heap-priority-queue"],
+    },
+    "693": { topicTags: ["bit-manipulation"] },
+    "694": {
+      topicTags: ["depth-first-search", "breadth-first-search", "union-find", "hash-table", "hash-function"],
+    },
+    "695": {
+      topicTags: ["depth-first-search", "breadth-first-search", "union-find", "array", "matrix"],
+    },
+    "696": { topicTags: ["two-pointers", "string"] },
+    "697": { topicTags: ["array", "hash-table"] },
+    "698": {
+      topicTags: ["bit-manipulation", "memoization", "array", "dynamic-programming", "backtracking", "bitmask"],
+    },
+    "699": { topicTags: ["segment-tree", "array", "ordered-set"] },
+    "700": { topicTags: ["tree", "binary-search-tree", "binary-tree"] },
+    "701": { topicTags: ["tree", "binary-search-tree", "binary-tree"] },
+    "702": { topicTags: ["array", "binary-search", "interactive"] },
+    "703": {
+      topicTags: ["tree", "design", "binary-search-tree", "binary-tree", "data-stream", "heap-priority-queue"],
+    },
+    "704": { topicTags: ["array", "binary-search"] },
+    "705": {
+      topicTags: ["design", "array", "hash-table", "linked-list", "hash-function"],
+    },
+    "706": {
+      topicTags: ["design", "array", "hash-table", "linked-list", "hash-function"],
+    },
+    "707": { topicTags: ["design", "linked-list"] },
+    "708": { topicTags: ["linked-list"] },
+    "709": { topicTags: ["string"] },
+    "710": {
+      topicTags: ["hash-table", "math", "binary-search", "sorting", "randomized"],
+    },
+    "711": {
+      topicTags: ["depth-first-search", "breadth-first-search", "union-find", "hash-table", "hash-function"],
+    },
+    "712": { topicTags: ["string", "dynamic-programming"] },
+    "713": { topicTags: ["array", "sliding-window"] },
+    "714": { topicTags: ["greedy", "array", "dynamic-programming"] },
+    "715": { topicTags: ["design", "segment-tree", "ordered-set"] },
+    "716": {
+      topicTags: ["stack", "design", "linked-list", "doubly-linked-list", "ordered-set"],
+    },
+    "717": { topicTags: ["array"] },
+    "718": {
+      topicTags: ["array", "binary-search", "dynamic-programming", "sliding-window", "hash-function", "rolling-hash"],
+    },
+    "719": { topicTags: ["array", "two-pointers", "binary-search", "sorting"] },
+    "720": { topicTags: ["trie", "array", "hash-table", "string", "sorting"] },
+    "721": {
+      topicTags: ["depth-first-search", "breadth-first-search", "union-find", "array", "string"],
+    },
+    "722": { topicTags: ["array", "string"] },
+    "723": { topicTags: ["array", "two-pointers", "matrix", "simulation"] },
+    "724": { topicTags: ["array", "prefix-sum"] },
+    "725": { topicTags: ["linked-list"] },
+    "726": { topicTags: ["stack", "hash-table", "string", "sorting"] },
+    "727": { topicTags: ["string", "dynamic-programming", "sliding-window"] },
+    "728": { topicTags: ["math"] },
+    "729": {
+      topicTags: ["design", "segment-tree", "binary-search", "ordered-set"],
+    },
+    "730": { topicTags: ["string", "dynamic-programming"] },
+    "731": {
+      topicTags: ["design", "segment-tree", "binary-search", "ordered-set"],
+    },
+    "732": {
+      topicTags: ["design", "segment-tree", "binary-search", "ordered-set"],
+    },
+    "733": {
+      topicTags: ["depth-first-search", "breadth-first-search", "array", "matrix"],
+    },
+    "734": { topicTags: ["array", "hash-table", "string"] },
+    "735": { topicTags: ["stack", "array"] },
+    "736": { topicTags: ["stack", "recursion", "hash-table", "string"] },
+    "737": {
+      topicTags: ["depth-first-search", "breadth-first-search", "union-find", "array", "hash-table", "string"],
+    },
+    "738": { topicTags: ["greedy", "math"] },
+    "739": { topicTags: ["stack", "array", "monotonic-stack"] },
+    "740": { topicTags: ["array", "hash-table", "dynamic-programming"] },
+    "741": { topicTags: ["array", "dynamic-programming", "matrix"] },
+    "742": {
+      topicTags: ["tree", "depth-first-search", "breadth-first-search", "binary-tree"],
+    },
+    "743": {
+      topicTags: ["depth-first-search", "breadth-first-search", "graph", "shortest-path", "heap-priority-queue"],
+    },
+    "744": { topicTags: ["array", "binary-search"] },
+    "745": { topicTags: ["design", "trie", "hash-table", "string"] },
+    "746": { topicTags: ["array", "dynamic-programming"] },
+    "747": { topicTags: ["array", "sorting"] },
+    "748": { topicTags: ["array", "hash-table", "string"] },
+    "749": {
+      topicTags: ["depth-first-search", "breadth-first-search", "array", "matrix", "simulation"],
+    },
+    "750": { topicTags: ["array", "math", "dynamic-programming", "matrix"] },
+    "751": { topicTags: ["bit-manipulation", "string"] },
+    "752": {
+      topicTags: ["breadth-first-search", "array", "hash-table", "string"],
+    },
+    "753": { topicTags: ["depth-first-search", "graph", "eulerian-circuit"] },
+    "754": { topicTags: ["math", "binary-search"] },
+    "755": { topicTags: ["array", "simulation"] },
+    "756": {
+      topicTags: ["bit-manipulation", "depth-first-search", "breadth-first-search"],
+    },
+    "757": { topicTags: ["greedy", "array", "sorting"] },
+    "758": {
+      topicTags: ["trie", "array", "hash-table", "string", "string-matching"],
+    },
+    "759": { topicTags: ["array", "sorting", "heap-priority-queue"] },
+    "760": { topicTags: ["array", "hash-table"] },
+    "761": { topicTags: ["recursion", "string"] },
+    "762": { topicTags: ["bit-manipulation", "math"] },
+    "763": { topicTags: ["greedy", "hash-table", "two-pointers", "string"] },
+    "764": { topicTags: ["array", "dynamic-programming"] },
+    "765": {
+      topicTags: ["greedy", "depth-first-search", "breadth-first-search", "union-find", "graph"],
+    },
+    "766": { topicTags: ["array", "matrix"] },
+    "767": {
+      topicTags: ["greedy", "hash-table", "string", "counting", "sorting", "heap-priority-queue"],
+    },
+    "768": {
+      topicTags: ["stack", "greedy", "array", "sorting", "monotonic-stack"],
+    },
+    "769": {
+      topicTags: ["stack", "greedy", "array", "sorting", "monotonic-stack"],
+    },
+    "770": {
+      topicTags: ["stack", "recursion", "hash-table", "math", "string"],
+    },
+    "771": { topicTags: ["hash-table", "string"] },
+    "772": { topicTags: ["stack", "recursion", "math", "string"] },
+    "773": { topicTags: ["breadth-first-search", "array", "matrix"] },
+    "774": { topicTags: ["array", "binary-search"] },
+    "775": { topicTags: ["array", "math"] },
+    "776": {
+      topicTags: ["tree", "binary-search-tree", "recursion", "binary-tree"],
+    },
+    "777": { topicTags: ["two-pointers", "string"] },
+    "778": {
+      topicTags: [
+        "depth-first-search",
+        "breadth-first-search",
+        "union-find",
+        "array",
+        "binary-search",
+        "matrix",
+        "heap-priority-queue",
+      ],
+    },
+    "779": { topicTags: ["bit-manipulation", "recursion", "math"] },
+    "780": { topicTags: ["math"] },
+    "781": { topicTags: ["greedy", "array", "hash-table", "math"] },
+    "782": { topicTags: ["bit-manipulation", "array", "math", "matrix"] },
+    "783": {
+      topicTags: ["tree", "depth-first-search", "breadth-first-search", "binary-search-tree", "binary-tree"],
+    },
+    "784": { topicTags: ["bit-manipulation", "string", "backtracking"] },
+    "785": {
+      topicTags: ["depth-first-search", "breadth-first-search", "union-find", "graph"],
+    },
+    "786": {
+      topicTags: ["array", "binary-search", "sorting", "heap-priority-queue"],
+    },
+    "787": {
+      topicTags: [
+        "depth-first-search",
+        "breadth-first-search",
+        "graph",
+        "dynamic-programming",
+        "shortest-path",
+        "heap-priority-queue",
+      ],
+    },
+    "788": { topicTags: ["math", "dynamic-programming"] },
+    "789": { topicTags: ["array", "math"] },
+    "790": { topicTags: ["dynamic-programming"] },
+    "791": { topicTags: ["hash-table", "string", "sorting"] },
+    "792": { topicTags: ["trie", "hash-table", "string", "sorting"] },
+    "793": { topicTags: ["math", "binary-search"] },
+    "794": { topicTags: ["array", "string"] },
+    "795": { topicTags: ["array", "two-pointers"] },
+    "796": { topicTags: ["string", "string-matching"] },
+    "797": {
+      topicTags: ["depth-first-search", "breadth-first-search", "graph", "backtracking"],
+    },
+    "798": { topicTags: ["array", "prefix-sum"] },
+    "799": { topicTags: ["dynamic-programming"] },
+    "800": { topicTags: ["math", "string", "enumeration"] },
+    "801": { topicTags: ["array", "dynamic-programming"] },
+    "802": {
+      topicTags: ["depth-first-search", "breadth-first-search", "graph", "topological-sort"],
+    },
+    "803": { topicTags: ["union-find", "array", "matrix"] },
+    "804": { topicTags: ["array", "hash-table", "string"] },
+    "805": {
+      topicTags: ["bit-manipulation", "array", "math", "dynamic-programming", "bitmask"],
+    },
+    "806": { topicTags: ["array", "string"] },
+    "807": { topicTags: ["greedy", "array", "matrix"] },
+    "808": {
+      topicTags: ["math", "dynamic-programming", "probability-and-statistics"],
+    },
+    "809": { topicTags: ["array", "two-pointers", "string"] },
+    "810": {
+      topicTags: ["bit-manipulation", "brainteaser", "array", "math", "game-theory"],
+    },
+    "811": { topicTags: ["array", "hash-table", "string", "counting"] },
+    "812": { topicTags: ["geometry", "array", "math"] },
+    "813": { topicTags: ["array", "dynamic-programming"] },
+    "814": { topicTags: ["tree", "depth-first-search", "binary-tree"] },
+    "815": { topicTags: ["breadth-first-search", "array", "hash-table"] },
+    "816": { topicTags: ["string", "backtracking"] },
+    "817": { topicTags: ["array", "hash-table", "linked-list"] },
+    "818": { topicTags: ["dynamic-programming"] },
+    "819": { topicTags: ["hash-table", "string", "counting"] },
+    "820": { topicTags: ["trie", "array", "hash-table", "string"] },
+    "821": { topicTags: ["array", "two-pointers", "string"] },
+    "822": { topicTags: ["array", "hash-table"] },
+    "823": { topicTags: ["array", "hash-table", "dynamic-programming"] },
+    "824": { topicTags: ["string"] },
+    "825": { topicTags: ["array", "two-pointers", "binary-search", "sorting"] },
+    "826": {
+      topicTags: ["greedy", "array", "two-pointers", "binary-search", "sorting"],
+    },
+    "827": {
+      topicTags: ["depth-first-search", "breadth-first-search", "union-find", "array", "matrix"],
+    },
+    "828": { topicTags: ["hash-table", "string", "dynamic-programming"] },
+    "829": { topicTags: ["math", "enumeration"] },
+    "830": { topicTags: ["string"] },
+    "831": { topicTags: ["string"] },
+    "832": { topicTags: ["array", "two-pointers", "matrix", "simulation"] },
+    "833": { topicTags: ["array", "string", "sorting"] },
+    "834": {
+      topicTags: ["tree", "depth-first-search", "graph", "dynamic-programming"],
+    },
+    "835": { topicTags: ["array", "matrix"] },
+    "836": { topicTags: ["geometry", "math"] },
+    "837": {
+      topicTags: ["math", "dynamic-programming", "sliding-window", "probability-and-statistics"],
+    },
+    "838": { topicTags: ["two-pointers", "string", "dynamic-programming"] },
+    "839": {
+      topicTags: ["depth-first-search", "breadth-first-search", "union-find", "array", "string"],
+    },
+    "840": { topicTags: ["array", "math", "matrix"] },
+    "841": {
+      topicTags: ["depth-first-search", "breadth-first-search", "graph"],
+    },
+    "842": { topicTags: ["string", "backtracking"] },
+    "843": {
+      topicTags: ["array", "math", "string", "game-theory", "interactive"],
+    },
+    "844": { topicTags: ["stack", "two-pointers", "string", "simulation"] },
+    "845": {
+      topicTags: ["array", "two-pointers", "dynamic-programming", "enumeration"],
+    },
+    "846": { topicTags: ["greedy", "array", "hash-table", "sorting"] },
+    "847": {
+      topicTags: ["bit-manipulation", "breadth-first-search", "graph", "dynamic-programming", "bitmask"],
+    },
+    "848": { topicTags: ["array", "string"] },
+    "849": { topicTags: ["array"] },
+    "850": {
+      topicTags: ["segment-tree", "array", "ordered-set", "line-sweep"],
+    },
+    "851": {
+      topicTags: ["depth-first-search", "graph", "topological-sort", "array"],
+    },
+    "852": { topicTags: ["array", "binary-search"] },
+    "853": { topicTags: ["stack", "array", "sorting", "monotonic-stack"] },
+    "854": { topicTags: ["breadth-first-search", "string"] },
+    "855": { topicTags: ["design", "ordered-set"] },
+    "856": { topicTags: ["stack", "string"] },
+    "857": { topicTags: ["greedy", "array", "sorting", "heap-priority-queue"] },
+    "858": { topicTags: ["geometry", "math"] },
+    "859": { topicTags: ["hash-table", "string"] },
+    "860": { topicTags: ["greedy", "array"] },
+    "861": { topicTags: ["greedy", "bit-manipulation", "array", "matrix"] },
+    "862": {
+      topicTags: [
+        "queue",
+        "array",
+        "binary-search",
+        "prefix-sum",
+        "sliding-window",
+        "monotonic-queue",
+        "heap-priority-queue",
+      ],
+    },
+    "863": {
+      topicTags: ["tree", "depth-first-search", "breadth-first-search", "binary-tree"],
+    },
+    "864": { topicTags: ["bit-manipulation", "breadth-first-search"] },
+    "865": {
+      topicTags: ["tree", "depth-first-search", "breadth-first-search", "hash-table", "binary-tree"],
+    },
+    "866": { topicTags: ["math"] },
+    "867": { topicTags: ["array", "matrix", "simulation"] },
+    "868": { topicTags: ["bit-manipulation"] },
+    "869": { topicTags: ["math", "counting", "enumeration", "sorting"] },
+    "870": { topicTags: ["greedy", "array", "two-pointers", "sorting"] },
+    "871": {
+      topicTags: ["greedy", "array", "dynamic-programming", "heap-priority-queue"],
+    },
+    "872": { topicTags: ["tree", "depth-first-search", "binary-tree"] },
+    "873": { topicTags: ["array", "hash-table", "dynamic-programming"] },
+    "874": { topicTags: ["array", "simulation"] },
+    "875": { topicTags: ["array", "binary-search"] },
+    "876": { topicTags: ["linked-list", "two-pointers"] },
+    "877": {
+      topicTags: ["array", "math", "dynamic-programming", "game-theory"],
+    },
+    "878": { topicTags: ["math", "binary-search"] },
+    "879": { topicTags: ["array", "dynamic-programming"] },
+    "880": { topicTags: ["stack", "string"] },
+    "881": { topicTags: ["greedy", "array", "two-pointers", "sorting"] },
+    "882": { topicTags: ["graph", "shortest-path", "heap-priority-queue"] },
+    "883": { topicTags: ["geometry", "array", "math", "matrix"] },
+    "884": { topicTags: ["hash-table", "string"] },
+    "885": { topicTags: ["array", "matrix", "simulation"] },
+    "886": {
+      topicTags: ["depth-first-search", "breadth-first-search", "union-find", "graph"],
+    },
+    "887": { topicTags: ["math", "binary-search", "dynamic-programming"] },
+    "888": { topicTags: ["array", "hash-table", "binary-search", "sorting"] },
+    "889": {
+      topicTags: ["tree", "array", "hash-table", "divide-and-conquer", "binary-tree"],
+    },
+    "890": { topicTags: ["array", "hash-table", "string"] },
+    "891": { topicTags: ["array", "math", "sorting"] },
+    "892": { topicTags: ["geometry", "array", "math", "matrix"] },
+    "893": { topicTags: ["array", "hash-table", "string"] },
+    "894": {
+      topicTags: ["tree", "recursion", "memoization", "dynamic-programming", "binary-tree"],
+    },
+    "895": { topicTags: ["stack", "design", "hash-table", "ordered-set"] },
+    "896": { topicTags: ["array"] },
+    "897": {
+      topicTags: ["stack", "tree", "depth-first-search", "binary-search-tree", "binary-tree"],
+    },
+    "898": { topicTags: ["bit-manipulation", "array", "dynamic-programming"] },
+    "899": { topicTags: ["math", "string", "sorting"] },
+    "900": { topicTags: ["design", "array", "counting", "iterator"] },
+    "901": { topicTags: ["stack", "design", "data-stream", "monotonic-stack"] },
+    "902": {
+      topicTags: ["array", "math", "string", "binary-search", "dynamic-programming"],
+    },
+    "903": { topicTags: ["dynamic-programming"] },
+    "904": { topicTags: ["array", "hash-table", "sliding-window"] },
+    "905": { topicTags: ["array", "two-pointers", "sorting"] },
+    "906": { topicTags: ["math", "enumeration"] },
+    "907": {
+      topicTags: ["stack", "array", "dynamic-programming", "monotonic-stack"],
+    },
+    "908": { topicTags: ["array", "math"] },
+    "909": { topicTags: ["breadth-first-search", "array", "matrix"] },
+    "910": { topicTags: ["greedy", "array", "math", "sorting"] },
+    "911": { topicTags: ["design", "array", "hash-table", "binary-search"] },
+    "912": {
+      topicTags: [
+        "array",
+        "divide-and-conquer",
+        "bucket-sort",
+        "counting-sort",
+        "radix-sort",
+        "sorting",
+        "heap-priority-queue",
+        "merge-sort",
+      ],
+    },
+    "913": {
+      topicTags: ["graph", "topological-sort", "memoization", "math", "dynamic-programming", "game-theory"],
+    },
+    "914": {
+      topicTags: ["array", "hash-table", "math", "counting", "number-theory"],
+    },
+    "915": { topicTags: ["array"] },
+    "916": { topicTags: ["array", "hash-table", "string"] },
+    "917": { topicTags: ["two-pointers", "string"] },
+    "918": {
+      topicTags: ["queue", "array", "divide-and-conquer", "dynamic-programming", "monotonic-queue"],
+    },
+    "919": {
+      topicTags: ["tree", "breadth-first-search", "design", "binary-tree"],
+    },
+    "920": { topicTags: ["math", "dynamic-programming", "combinatorics"] },
+    "921": { topicTags: ["stack", "greedy", "string"] },
+    "922": { topicTags: ["array", "two-pointers", "sorting"] },
+    "923": {
+      topicTags: ["array", "hash-table", "two-pointers", "counting", "sorting"],
+    },
+    "924": {
+      topicTags: ["depth-first-search", "breadth-first-search", "union-find", "array", "matrix"],
+    },
+    "925": { topicTags: ["two-pointers", "string"] },
+    "926": { topicTags: ["string", "dynamic-programming"] },
+    "927": { topicTags: ["array", "math"] },
+    "928": {
+      topicTags: ["depth-first-search", "breadth-first-search", "union-find", "array", "matrix"],
+    },
+    "929": { topicTags: ["array", "hash-table", "string"] },
+    "930": {
+      topicTags: ["array", "hash-table", "prefix-sum", "sliding-window"],
+    },
+    "931": { topicTags: ["array", "dynamic-programming", "matrix"] },
+    "932": { topicTags: ["array", "math", "divide-and-conquer"] },
+    "933": { topicTags: ["design", "queue", "data-stream"] },
+    "934": {
+      topicTags: ["depth-first-search", "breadth-first-search", "array", "matrix"],
+    },
+    "935": { topicTags: ["dynamic-programming"] },
+    "936": { topicTags: ["stack", "greedy", "queue", "string"] },
+    "937": { topicTags: ["array", "string", "sorting"] },
+    "938": {
+      topicTags: ["tree", "depth-first-search", "binary-search-tree", "binary-tree"],
+    },
+    "939": {
+      topicTags: ["geometry", "array", "hash-table", "math", "sorting"],
+    },
+    "940": { topicTags: ["string", "dynamic-programming"] },
+    "941": { topicTags: ["array"] },
+    "942": { topicTags: ["greedy", "array", "two-pointers", "string"] },
+    "943": {
+      topicTags: ["bit-manipulation", "array", "string", "dynamic-programming", "bitmask"],
+    },
+    "944": { topicTags: ["array", "string"] },
+    "945": { topicTags: ["greedy", "array", "counting", "sorting"] },
+    "946": { topicTags: ["stack", "array", "simulation"] },
+    "947": { topicTags: ["depth-first-search", "union-find", "graph"] },
+    "948": { topicTags: ["greedy", "array", "two-pointers", "sorting"] },
+    "949": { topicTags: ["string", "enumeration"] },
+    "950": { topicTags: ["queue", "array", "sorting", "simulation"] },
+    "951": { topicTags: ["tree", "depth-first-search", "binary-tree"] },
+    "952": { topicTags: ["union-find", "array", "math"] },
+    "953": { topicTags: ["array", "hash-table", "string"] },
+    "954": { topicTags: ["greedy", "array", "hash-table", "sorting"] },
+    "955": { topicTags: ["greedy", "array", "string"] },
+    "956": { topicTags: ["array", "dynamic-programming"] },
+    "957": { topicTags: ["bit-manipulation", "array", "hash-table", "math"] },
+    "958": { topicTags: ["tree", "breadth-first-search", "binary-tree"] },
+    "959": {
+      topicTags: ["depth-first-search", "breadth-first-search", "union-find", "graph"],
+    },
+    "960": { topicTags: ["array", "string", "dynamic-programming"] },
+    "961": { topicTags: ["array", "hash-table"] },
+    "962": { topicTags: ["stack", "array", "monotonic-stack"] },
+    "963": { topicTags: ["geometry", "array", "math"] },
+    "964": { topicTags: ["math", "dynamic-programming"] },
+    "965": {
+      topicTags: ["tree", "depth-first-search", "breadth-first-search", "binary-tree"],
+    },
+    "966": { topicTags: ["array", "hash-table", "string"] },
+    "967": { topicTags: ["breadth-first-search", "backtracking"] },
+    "968": {
+      topicTags: ["tree", "depth-first-search", "dynamic-programming", "binary-tree"],
+    },
+    "969": { topicTags: ["greedy", "array", "two-pointers", "sorting"] },
+    "970": { topicTags: ["hash-table", "math"] },
+    "971": { topicTags: ["tree", "depth-first-search", "binary-tree"] },
+    "972": { topicTags: ["math", "string"] },
+    "973": {
+      topicTags: ["geometry", "array", "math", "divide-and-conquer", "quickselect", "sorting", "heap-priority-queue"],
+    },
+    "974": { topicTags: ["array", "hash-table", "prefix-sum"] },
+    "975": {
+      topicTags: ["stack", "array", "dynamic-programming", "ordered-set", "monotonic-stack"],
+    },
+    "976": { topicTags: ["greedy", "array", "math", "sorting"] },
+    "977": { topicTags: ["array", "two-pointers", "sorting"] },
+    "978": { topicTags: ["array", "dynamic-programming", "sliding-window"] },
+    "979": { topicTags: ["tree", "depth-first-search", "binary-tree"] },
+    "980": {
+      topicTags: ["bit-manipulation", "array", "backtracking", "matrix"],
+    },
+    "981": { topicTags: ["design", "hash-table", "string", "binary-search"] },
+    "982": { topicTags: ["bit-manipulation", "array", "hash-table"] },
+    "983": { topicTags: ["array", "dynamic-programming"] },
+    "984": { topicTags: ["greedy", "string"] },
+    "985": { topicTags: ["array", "simulation"] },
+    "986": { topicTags: ["array", "two-pointers"] },
+    "987": {
+      topicTags: ["tree", "depth-first-search", "breadth-first-search", "hash-table", "binary-tree"],
+    },
+    "988": {
+      topicTags: ["tree", "depth-first-search", "string", "binary-tree"],
+    },
+    "989": { topicTags: ["array", "math"] },
+    "990": { topicTags: ["union-find", "graph", "array", "string"] },
+    "991": { topicTags: ["greedy", "math"] },
+    "992": { topicTags: ["array", "hash-table", "counting", "sliding-window"] },
+    "993": {
+      topicTags: ["tree", "depth-first-search", "breadth-first-search", "binary-tree"],
+    },
+    "994": { topicTags: ["breadth-first-search", "array", "matrix"] },
+    "995": {
+      topicTags: ["bit-manipulation", "queue", "array", "prefix-sum", "sliding-window"],
+    },
+    "996": {
+      topicTags: ["bit-manipulation", "array", "math", "dynamic-programming", "backtracking", "bitmask"],
+    },
+    "997": { topicTags: ["graph", "array", "hash-table"] },
+    "998": { topicTags: ["tree", "binary-tree"] },
+    "999": { topicTags: ["array", "matrix", "simulation"] },
+    "1000": { topicTags: ["array", "dynamic-programming"] },
+    "1001": { topicTags: ["array", "hash-table"] },
+    "1002": { topicTags: ["array", "hash-table", "string"] },
+    "1003": { topicTags: ["stack", "string"] },
+    "1004": {
+      topicTags: ["array", "binary-search", "prefix-sum", "sliding-window"],
+    },
+    "1005": { topicTags: ["greedy", "array", "sorting"] },
+    "1006": { topicTags: ["stack", "math", "simulation"] },
+    "1007": { topicTags: ["greedy", "array"] },
+    "1008": {
+      topicTags: ["stack", "tree", "binary-search-tree", "array", "binary-tree", "monotonic-stack"],
+    },
+    "1009": { topicTags: ["bit-manipulation"] },
+    "1010": { topicTags: ["array", "hash-table", "counting"] },
+    "1011": { topicTags: ["array", "binary-search"] },
+    "1012": { topicTags: ["math", "dynamic-programming"] },
+    "1013": { topicTags: ["greedy", "array"] },
+    "1014": { topicTags: ["array", "dynamic-programming"] },
+    "1015": { topicTags: ["hash-table", "math"] },
+    "1016": { topicTags: ["string"] },
+    "1017": { topicTags: ["math"] },
+    "1018": { topicTags: ["array"] },
+    "1019": { topicTags: ["stack", "array", "linked-list", "monotonic-stack"] },
+    "1020": {
+      topicTags: ["depth-first-search", "breadth-first-search", "union-find", "array", "matrix"],
+    },
+    "1021": { topicTags: ["stack", "string"] },
+    "1022": { topicTags: ["tree", "depth-first-search", "binary-tree"] },
+    "1023": {
+      topicTags: ["trie", "two-pointers", "string", "string-matching"],
+    },
+    "1024": { topicTags: ["greedy", "array", "dynamic-programming"] },
+    "1025": {
+      topicTags: ["brainteaser", "math", "dynamic-programming", "game-theory"],
+    },
+    "1026": { topicTags: ["tree", "depth-first-search", "binary-tree"] },
+    "1027": {
+      topicTags: ["array", "hash-table", "binary-search", "dynamic-programming"],
+    },
+    "1028": {
+      topicTags: ["tree", "depth-first-search", "string", "binary-tree"],
+    },
+    "1029": { topicTags: ["greedy", "array", "sorting"] },
+    "1030": { topicTags: ["geometry", "array", "math", "matrix", "sorting"] },
+    "1031": { topicTags: ["array", "dynamic-programming", "sliding-window"] },
+    "1032": { topicTags: ["design", "trie", "array", "string", "data-stream"] },
+    "1033": { topicTags: ["brainteaser", "math"] },
+    "1034": {
+      topicTags: ["depth-first-search", "breadth-first-search", "array", "matrix"],
+    },
+    "1035": { topicTags: ["array", "dynamic-programming"] },
+    "1036": {
+      topicTags: ["depth-first-search", "breadth-first-search", "array", "hash-table"],
+    },
+    "1037": { topicTags: ["geometry", "array", "math"] },
+    "1038": {
+      topicTags: ["tree", "depth-first-search", "binary-search-tree", "binary-tree"],
+    },
+    "1039": { topicTags: ["array", "dynamic-programming"] },
+    "1040": { topicTags: ["array", "math", "two-pointers", "sorting"] },
+    "1041": { topicTags: ["math", "string", "simulation"] },
+    "1042": {
+      topicTags: ["depth-first-search", "breadth-first-search", "graph"],
+    },
+    "1043": { topicTags: ["array", "dynamic-programming"] },
+    "1044": {
+      topicTags: ["string", "binary-search", "suffix-array", "sliding-window", "hash-function", "rolling-hash"],
+    },
+    "1045": { topicTags: ["database"] },
+    "1046": { topicTags: ["array", "heap-priority-queue"] },
+    "1047": { topicTags: ["stack", "string"] },
+    "1048": {
+      topicTags: ["array", "hash-table", "two-pointers", "string", "dynamic-programming"],
+    },
+    "1049": { topicTags: ["array", "dynamic-programming"] },
+    "1050": { topicTags: ["database"] },
+    "1051": { topicTags: ["array", "counting-sort", "sorting"] },
+    "1052": { topicTags: ["array", "sliding-window"] },
+    "1053": { topicTags: ["greedy", "array"] },
+    "1054": {
+      topicTags: ["greedy", "array", "hash-table", "counting", "sorting", "heap-priority-queue"],
+    },
+    "1055": { topicTags: ["greedy", "string", "dynamic-programming"] },
+    "1056": { topicTags: ["math"] },
+    "1057": { topicTags: ["greedy", "array", "sorting"] },
+    "1058": { topicTags: ["greedy", "array", "math", "string"] },
+    "1059": { topicTags: ["depth-first-search", "graph"] },
+    "1060": { topicTags: ["array", "binary-search"] },
+    "1061": { topicTags: ["union-find", "string"] },
+    "1062": {
+      topicTags: ["string", "binary-search", "dynamic-programming", "suffix-array", "hash-function", "rolling-hash"],
+    },
+    "1063": { topicTags: ["stack", "array", "monotonic-stack"] },
+    "1064": { topicTags: ["array", "binary-search"] },
+    "1065": { topicTags: ["trie", "array", "string", "sorting"] },
+    "1066": {
+      topicTags: ["bit-manipulation", "array", "dynamic-programming", "backtracking", "bitmask"],
+    },
+    "1067": { topicTags: ["math", "dynamic-programming"] },
+    "1068": { topicTags: ["database"] },
+    "1069": { topicTags: ["database"] },
+    "1070": { topicTags: ["database"] },
+    "1071": { topicTags: ["math", "string"] },
+    "1072": { topicTags: ["array", "hash-table", "matrix"] },
+    "1073": { topicTags: ["array", "math"] },
+    "1074": { topicTags: ["array", "hash-table", "matrix", "prefix-sum"] },
+    "1075": { topicTags: ["database"] },
+    "1076": { topicTags: ["database"] },
+    "1077": { topicTags: ["database"] },
+    "1078": { topicTags: ["string"] },
+    "1079": { topicTags: ["string", "backtracking"] },
+    "1080": { topicTags: ["tree", "depth-first-search", "binary-tree"] },
+    "1081": { topicTags: ["stack", "greedy", "string", "monotonic-stack"] },
+    "1082": { topicTags: ["database"] },
+    "1083": { topicTags: ["database"] },
+    "1084": { topicTags: ["database"] },
+    "1085": { topicTags: ["array", "math"] },
+    "1086": { topicTags: ["array", "hash-table", "sorting"] },
+    "1087": { topicTags: ["breadth-first-search", "string", "backtracking"] },
+    "1088": { topicTags: ["math", "backtracking"] },
+    "1089": { topicTags: ["array", "two-pointers"] },
+    "1090": {
+      topicTags: ["greedy", "array", "hash-table", "counting", "sorting"],
+    },
+    "1091": { topicTags: ["breadth-first-search", "array", "matrix"] },
+    "1092": { topicTags: ["string", "dynamic-programming"] },
+    "1093": {
+      topicTags: ["math", "two-pointers", "probability-and-statistics"],
+    },
+    "1094": {
+      topicTags: ["array", "prefix-sum", "sorting", "simulation", "heap-priority-queue"],
+    },
+    "1095": { topicTags: ["array", "binary-search", "interactive"] },
+    "1096": {
+      topicTags: ["stack", "breadth-first-search", "string", "backtracking"],
+    },
+    "1097": { topicTags: ["database"] },
+    "1098": { topicTags: ["database"] },
+    "1099": {
+      topicTags: ["array", "two-pointers", "binary-search", "sorting"],
+    },
+    "1100": { topicTags: ["hash-table", "string", "sliding-window"] },
+    "1101": { topicTags: ["union-find", "array"] },
+    "1102": {
+      topicTags: ["depth-first-search", "breadth-first-search", "union-find", "array", "matrix", "heap-priority-queue"],
+    },
+    "1103": { topicTags: ["math", "simulation"] },
+    "1104": { topicTags: ["tree", "math", "binary-tree"] },
+    "1105": { topicTags: ["array", "dynamic-programming"] },
+    "1106": { topicTags: ["stack", "recursion", "string"] },
+    "1107": { topicTags: ["database"] },
+    "1108": { topicTags: ["string"] },
+    "1109": { topicTags: ["array", "prefix-sum"] },
+    "1110": { topicTags: ["tree", "depth-first-search", "binary-tree"] },
+    "1111": { topicTags: ["stack", "string"] },
+    "1112": { topicTags: ["database"] },
+    "1113": { topicTags: ["database"] },
+    "1114": { topicTags: ["concurrency"] },
+    "1115": { topicTags: ["concurrency"] },
+    "1116": { topicTags: ["concurrency"] },
+    "1117": { topicTags: ["concurrency"] },
+    "1118": { topicTags: ["math"] },
+    "1119": { topicTags: ["string"] },
+    "1120": { topicTags: ["tree", "depth-first-search", "binary-tree"] },
+    "1121": { topicTags: ["greedy", "array"] },
+    "1122": { topicTags: ["array", "hash-table", "counting-sort", "sorting"] },
+    "1123": {
+      topicTags: ["tree", "depth-first-search", "breadth-first-search", "hash-table", "binary-tree"],
+    },
+    "1124": {
+      topicTags: ["stack", "array", "hash-table", "prefix-sum", "monotonic-stack"],
+    },
+    "1125": {
+      topicTags: ["bit-manipulation", "array", "dynamic-programming", "bitmask"],
+    },
+    "1126": { topicTags: ["database"] },
+    "1127": { topicTags: ["database"] },
+    "1128": { topicTags: ["array", "hash-table", "counting"] },
+    "1129": { topicTags: ["breadth-first-search", "graph"] },
+    "1130": {
+      topicTags: ["stack", "greedy", "dynamic-programming", "monotonic-stack"],
+    },
+    "1131": { topicTags: ["array", "math"] },
+    "1132": { topicTags: ["database"] },
+    "1133": { topicTags: ["array", "hash-table", "sorting"] },
+    "1134": { topicTags: ["math"] },
+    "1135": {
+      topicTags: ["union-find", "graph", "minimum-spanning-tree", "heap-priority-queue"],
+    },
+    "1136": { topicTags: ["graph", "topological-sort"] },
+    "1137": { topicTags: ["memoization", "math", "dynamic-programming"] },
+    "1138": { topicTags: ["hash-table", "string"] },
+    "1139": { topicTags: ["array", "dynamic-programming", "matrix"] },
+    "1140": {
+      topicTags: ["array", "math", "dynamic-programming", "game-theory"],
+    },
+    "1141": { topicTags: ["database"] },
+    "1142": { topicTags: ["database"] },
+    "1143": { topicTags: ["string", "dynamic-programming"] },
+    "1144": { topicTags: ["greedy", "array"] },
+    "1145": { topicTags: ["tree", "depth-first-search", "binary-tree"] },
+    "1146": { topicTags: ["design", "array", "hash-table", "binary-search"] },
+    "1147": {
+      topicTags: ["greedy", "two-pointers", "string", "dynamic-programming", "hash-function", "rolling-hash"],
+    },
+    "1148": { topicTags: ["database"] },
+    "1149": { topicTags: ["database"] },
+    "1150": { topicTags: ["array", "binary-search"] },
+    "1151": { topicTags: ["array", "sliding-window"] },
+    "1152": { topicTags: ["array", "hash-table", "sorting"] },
+    "1153": { topicTags: ["hash-table", "string"] },
+    "1154": { topicTags: ["math", "string"] },
+    "1155": { topicTags: ["dynamic-programming"] },
+    "1156": { topicTags: ["string", "sliding-window"] },
+    "1157": {
+      topicTags: ["design", "binary-indexed-tree", "segment-tree", "array", "binary-search"],
+    },
+    "1158": { topicTags: ["database"] },
+    "1159": { topicTags: ["database"] },
+    "1160": { topicTags: ["array", "hash-table", "string"] },
+    "1161": {
+      topicTags: ["tree", "depth-first-search", "breadth-first-search", "binary-tree"],
+    },
+    "1162": {
+      topicTags: ["breadth-first-search", "array", "dynamic-programming", "matrix"],
+    },
+    "1163": { topicTags: ["two-pointers", "string"] },
+    "1164": { topicTags: ["database"] },
+    "1165": { topicTags: ["hash-table", "string"] },
+    "1166": { topicTags: ["design", "trie", "hash-table", "string"] },
+    "1167": { topicTags: ["greedy", "array", "heap-priority-queue"] },
+    "1168": { topicTags: ["union-find", "graph", "minimum-spanning-tree"] },
+    "1169": { topicTags: ["array", "hash-table", "string", "sorting"] },
+    "1170": {
+      topicTags: ["array", "hash-table", "string", "binary-search", "sorting"],
+    },
+    "1171": { topicTags: ["hash-table", "linked-list"] },
+    "1172": {
+      topicTags: ["stack", "design", "hash-table", "heap-priority-queue"],
+    },
+    "1173": { topicTags: ["database"] },
+    "1174": { topicTags: ["database"] },
+    "1175": { topicTags: ["math"] },
+    "1176": { topicTags: ["array", "sliding-window"] },
+    "1177": {
+      topicTags: ["bit-manipulation", "hash-table", "string", "prefix-sum"],
+    },
+    "1178": {
+      topicTags: ["bit-manipulation", "trie", "array", "hash-table", "string"],
+    },
+    "1179": { topicTags: ["database"] },
+    "1180": { topicTags: ["math", "string"] },
+    "1181": { topicTags: ["array", "hash-table", "string", "sorting"] },
+    "1182": { topicTags: ["array", "binary-search", "dynamic-programming"] },
+    "1183": { topicTags: ["greedy", "heap-priority-queue"] },
+    "1184": { topicTags: ["array"] },
+    "1185": { topicTags: ["math"] },
+    "1186": { topicTags: ["array", "dynamic-programming"] },
+    "1187": { topicTags: ["array", "binary-search", "dynamic-programming"] },
+    "1188": { topicTags: ["concurrency"] },
+    "1189": { topicTags: ["hash-table", "string", "counting"] },
+    "1190": { topicTags: ["stack", "string"] },
+    "1191": { topicTags: ["array", "dynamic-programming"] },
+    "1192": {
+      topicTags: ["depth-first-search", "graph", "biconnected-component"],
+    },
+    "1193": { topicTags: ["database"] },
+    "1194": { topicTags: ["database"] },
+    "1195": { topicTags: ["concurrency"] },
+    "1196": { topicTags: ["greedy", "array", "sorting"] },
+    "1197": { topicTags: ["breadth-first-search"] },
+    "1198": {
+      topicTags: ["array", "hash-table", "binary-search", "counting", "matrix"],
+    },
+    "1199": { topicTags: ["greedy", "math", "heap-priority-queue"] },
+    "1200": { topicTags: ["array", "sorting"] },
+    "1201": { topicTags: ["math", "binary-search", "number-theory"] },
+    "1202": {
+      topicTags: ["depth-first-search", "breadth-first-search", "union-find", "hash-table", "string"],
+    },
+    "1203": {
+      topicTags: ["depth-first-search", "breadth-first-search", "graph", "topological-sort"],
+    },
+    "1204": { topicTags: ["database"] },
+    "1205": { topicTags: ["database"] },
+    "1206": { topicTags: ["design", "linked-list"] },
+    "1207": { topicTags: ["array", "hash-table"] },
+    "1208": {
+      topicTags: ["string", "binary-search", "prefix-sum", "sliding-window"],
+    },
+    "1209": { topicTags: ["stack", "string"] },
+    "1210": { topicTags: ["breadth-first-search", "array", "matrix"] },
+    "1211": { topicTags: ["database"] },
+    "1212": { topicTags: ["database"] },
+    "1213": { topicTags: ["array", "hash-table", "binary-search", "counting"] },
+    "1214": {
+      topicTags: [
+        "stack",
+        "tree",
+        "depth-first-search",
+        "binary-search-tree",
+        "two-pointers",
+        "binary-search",
+        "binary-tree",
+      ],
+    },
+    "1215": { topicTags: ["breadth-first-search", "backtracking"] },
+    "1216": { topicTags: ["string", "dynamic-programming"] },
+    "1217": { topicTags: ["greedy", "array", "math"] },
+    "1218": { topicTags: ["array", "hash-table", "dynamic-programming"] },
+    "1219": { topicTags: ["array", "backtracking", "matrix"] },
+    "1220": { topicTags: ["dynamic-programming"] },
+    "1221": { topicTags: ["greedy", "string", "counting"] },
+    "1222": { topicTags: ["array", "matrix", "simulation"] },
+    "1223": { topicTags: ["array", "dynamic-programming"] },
+    "1224": { topicTags: ["array", "hash-table"] },
+    "1225": { topicTags: ["database"] },
+    "1226": { topicTags: ["concurrency"] },
+    "1227": {
+      topicTags: ["brainteaser", "math", "dynamic-programming", "probability-and-statistics"],
+    },
+    "1228": { topicTags: ["array", "math"] },
+    "1229": { topicTags: ["array", "two-pointers", "sorting"] },
+    "1230": {
+      topicTags: ["math", "dynamic-programming", "probability-and-statistics"],
+    },
+    "1231": { topicTags: ["array", "binary-search"] },
+    "1232": { topicTags: ["geometry", "array", "math"] },
+    "1233": { topicTags: ["trie", "array", "string"] },
+    "1234": { topicTags: ["string", "sliding-window"] },
+    "1235": {
+      topicTags: ["array", "binary-search", "dynamic-programming", "sorting"],
+    },
+    "1236": {
+      topicTags: ["depth-first-search", "breadth-first-search", "string", "interactive"],
+    },
+    "1237": {
+      topicTags: ["math", "two-pointers", "binary-search", "interactive"],
+    },
+    "1238": { topicTags: ["bit-manipulation", "math", "backtracking"] },
+    "1239": {
+      topicTags: ["bit-manipulation", "array", "string", "backtracking"],
+    },
+    "1240": { topicTags: ["dynamic-programming", "backtracking"] },
+    "1241": { topicTags: ["database"] },
+    "1242": {
+      topicTags: ["depth-first-search", "breadth-first-search", "concurrency"],
+    },
+    "1243": { topicTags: ["array", "simulation"] },
+    "1244": { topicTags: ["design", "hash-table", "sorting"] },
+    "1245": {
+      topicTags: ["tree", "depth-first-search", "breadth-first-search", "graph", "topological-sort"],
+    },
+    "1246": { topicTags: ["array", "dynamic-programming"] },
+    "1247": { topicTags: ["greedy", "math", "string"] },
+    "1248": { topicTags: ["array", "hash-table", "math", "sliding-window"] },
+    "1249": { topicTags: ["stack", "string"] },
+    "1250": { topicTags: ["array", "math", "number-theory"] },
+    "1251": { topicTags: ["database"] },
+    "1252": { topicTags: ["array", "math", "simulation"] },
+    "1253": { topicTags: ["greedy", "array", "matrix"] },
+    "1254": {
+      topicTags: ["depth-first-search", "breadth-first-search", "union-find", "array", "matrix"],
+    },
+    "1255": {
+      topicTags: ["bit-manipulation", "array", "string", "dynamic-programming", "backtracking", "bitmask"],
+    },
+    "1256": { topicTags: ["bit-manipulation", "math", "string"] },
+    "1257": {
+      topicTags: ["tree", "depth-first-search", "breadth-first-search", "array", "hash-table", "string"],
+    },
+    "1258": {
+      topicTags: ["union-find", "array", "hash-table", "string", "backtracking"],
+    },
+    "1259": { topicTags: ["math", "dynamic-programming"] },
+    "1260": { topicTags: ["array", "matrix", "simulation"] },
+    "1261": {
+      topicTags: ["tree", "depth-first-search", "breadth-first-search", "design", "hash-table", "binary-tree"],
+    },
+    "1262": { topicTags: ["greedy", "array", "dynamic-programming"] },
+    "1263": {
+      topicTags: ["breadth-first-search", "array", "matrix", "heap-priority-queue"],
+    },
+    "1264": { topicTags: ["database"] },
+    "1265": {
+      topicTags: ["stack", "recursion", "linked-list", "two-pointers"],
+    },
+    "1266": { topicTags: ["geometry", "array", "math"] },
+    "1267": {
+      topicTags: ["depth-first-search", "breadth-first-search", "union-find", "array", "counting", "matrix"],
+    },
+    "1268": { topicTags: ["trie", "array", "string"] },
+    "1269": { topicTags: ["dynamic-programming"] },
+    "1270": { topicTags: ["database"] },
+    "1271": { topicTags: ["math", "string"] },
+    "1272": { topicTags: ["array"] },
+    "1273": {
+      topicTags: ["tree", "depth-first-search", "breadth-first-search"],
+    },
+    "1274": { topicTags: ["array", "divide-and-conquer", "interactive"] },
+    "1275": { topicTags: ["array", "hash-table", "matrix", "simulation"] },
+    "1276": { topicTags: ["math"] },
+    "1277": { topicTags: ["array", "dynamic-programming", "matrix"] },
+    "1278": { topicTags: ["string", "dynamic-programming"] },
+    "1279": { topicTags: ["concurrency"] },
+    "1280": { topicTags: ["database"] },
+    "1281": { topicTags: ["math"] },
+    "1282": { topicTags: ["array", "hash-table"] },
+    "1283": { topicTags: ["array", "binary-search"] },
+    "1284": {
+      topicTags: ["bit-manipulation", "breadth-first-search", "array", "matrix"],
+    },
+    "1285": { topicTags: ["database"] },
+    "1286": { topicTags: ["design", "string", "backtracking", "iterator"] },
+    "1287": { topicTags: ["array"] },
+    "1288": { topicTags: ["array", "sorting"] },
+    "1289": { topicTags: ["array", "dynamic-programming", "matrix"] },
+    "1290": { topicTags: ["linked-list", "math"] },
+    "1291": { topicTags: ["enumeration"] },
+    "1292": { topicTags: ["array", "binary-search", "matrix", "prefix-sum"] },
+    "1293": { topicTags: ["breadth-first-search", "array", "matrix"] },
+    "1294": { topicTags: ["database"] },
+    "1295": { topicTags: ["array"] },
+    "1296": { topicTags: ["greedy", "array", "hash-table", "sorting"] },
+    "1297": { topicTags: ["hash-table", "string", "sliding-window"] },
+    "1298": { topicTags: ["breadth-first-search", "array"] },
+    "1299": { topicTags: ["array"] },
+    "1300": { topicTags: ["array", "binary-search", "sorting"] },
+    "1301": { topicTags: ["array", "dynamic-programming", "matrix"] },
+    "1302": {
+      topicTags: ["tree", "depth-first-search", "breadth-first-search", "binary-tree"],
+    },
+    "1303": { topicTags: ["database"] },
+    "1304": { topicTags: ["array", "math"] },
+    "1305": {
+      topicTags: ["tree", "depth-first-search", "binary-search-tree", "binary-tree", "sorting"],
+    },
+    "1306": {
+      topicTags: ["depth-first-search", "breadth-first-search", "array"],
+    },
+    "1307": { topicTags: ["array", "math", "string", "backtracking"] },
+    "1308": { topicTags: ["database"] },
+    "1309": { topicTags: ["string"] },
+    "1310": { topicTags: ["bit-manipulation", "array", "prefix-sum"] },
+    "1311": {
+      topicTags: ["breadth-first-search", "array", "hash-table", "sorting"],
+    },
+    "1312": { topicTags: ["string", "dynamic-programming"] },
+    "1313": { topicTags: ["array"] },
+    "1314": { topicTags: ["array", "matrix", "prefix-sum"] },
+    "1315": {
+      topicTags: ["tree", "depth-first-search", "breadth-first-search", "binary-tree"],
+    },
+    "1316": { topicTags: ["trie", "string", "hash-function", "rolling-hash"] },
+    "1317": { topicTags: ["math"] },
+    "1318": { topicTags: ["bit-manipulation"] },
+    "1319": {
+      topicTags: ["depth-first-search", "breadth-first-search", "union-find", "graph"],
+    },
+    "1320": { topicTags: ["string", "dynamic-programming"] },
+    "1321": { topicTags: ["database"] },
+    "1322": { topicTags: ["database"] },
+    "1323": { topicTags: ["greedy", "math"] },
+    "1324": { topicTags: ["array", "string", "simulation"] },
+    "1325": { topicTags: ["tree", "depth-first-search", "binary-tree"] },
+    "1326": { topicTags: ["greedy", "array", "dynamic-programming"] },
+    "1327": { topicTags: ["database"] },
+    "1328": { topicTags: ["greedy", "string"] },
+    "1329": { topicTags: ["array", "matrix", "sorting"] },
+    "1330": { topicTags: ["greedy", "array", "math"] },
+    "1331": { topicTags: ["array", "hash-table", "sorting"] },
+    "1332": { topicTags: ["two-pointers", "string"] },
+    "1333": { topicTags: ["array", "sorting"] },
+    "1334": { topicTags: ["graph", "dynamic-programming", "shortest-path"] },
+    "1335": { topicTags: ["array", "dynamic-programming"] },
+    "1336": { topicTags: ["database"] },
+    "1337": {
+      topicTags: ["array", "binary-search", "matrix", "sorting", "heap-priority-queue"],
+    },
+    "1338": {
+      topicTags: ["greedy", "array", "hash-table", "sorting", "heap-priority-queue"],
+    },
+    "1339": { topicTags: ["tree", "depth-first-search", "binary-tree"] },
+    "1340": { topicTags: ["array", "dynamic-programming", "sorting"] },
+    "1341": { topicTags: ["database"] },
+    "1342": { topicTags: ["bit-manipulation", "math"] },
+    "1343": { topicTags: ["array", "sliding-window"] },
+    "1344": { topicTags: ["math"] },
+    "1345": { topicTags: ["breadth-first-search", "array", "hash-table"] },
+    "1346": {
+      topicTags: ["array", "hash-table", "two-pointers", "binary-search", "sorting"],
+    },
+    "1347": { topicTags: ["hash-table", "string", "counting"] },
+    "1348": {
+      topicTags: ["design", "hash-table", "binary-search", "ordered-set", "sorting"],
+    },
+    "1349": {
+      topicTags: ["bit-manipulation", "array", "dynamic-programming", "bitmask", "matrix"],
+    },
+    "1350": { topicTags: ["database"] },
+    "1351": { topicTags: ["array", "binary-search", "matrix"] },
+    "1352": { topicTags: ["design", "queue", "array", "math", "data-stream"] },
+    "1353": { topicTags: ["greedy", "array", "heap-priority-queue"] },
+    "1354": { topicTags: ["array", "heap-priority-queue"] },
+    "1355": { topicTags: ["database"] },
+    "1356": { topicTags: ["bit-manipulation", "array", "counting", "sorting"] },
+    "1357": { topicTags: ["design", "array", "hash-table"] },
+    "1358": { topicTags: ["hash-table", "string", "sliding-window"] },
+    "1359": { topicTags: ["math", "dynamic-programming", "combinatorics"] },
+    "1360": { topicTags: ["math", "string"] },
+    "1361": {
+      topicTags: ["tree", "depth-first-search", "breadth-first-search", "union-find", "graph", "binary-tree"],
+    },
+    "1362": { topicTags: ["math"] },
+    "1363": { topicTags: ["greedy", "array", "dynamic-programming"] },
+    "1364": { topicTags: ["database"] },
+    "1365": { topicTags: ["array", "hash-table", "counting", "sorting"] },
+    "1366": {
+      topicTags: ["array", "hash-table", "string", "counting", "sorting"],
+    },
+    "1367": {
+      topicTags: ["tree", "depth-first-search", "breadth-first-search", "linked-list", "binary-tree"],
+    },
+    "1368": {
+      topicTags: ["breadth-first-search", "graph", "array", "matrix", "shortest-path", "heap-priority-queue"],
+    },
+    "1369": { topicTags: ["database"] },
+    "1370": { topicTags: ["hash-table", "string", "counting"] },
+    "1371": {
+      topicTags: ["bit-manipulation", "hash-table", "string", "prefix-sum"],
+    },
+    "1372": {
+      topicTags: ["tree", "depth-first-search", "dynamic-programming", "binary-tree"],
+    },
+    "1373": {
+      topicTags: ["tree", "depth-first-search", "binary-search-tree", "dynamic-programming", "binary-tree"],
+    },
+    "1374": { topicTags: ["string"] },
+    "1375": { topicTags: ["array"] },
+    "1376": {
+      topicTags: ["tree", "depth-first-search", "breadth-first-search"],
+    },
+    "1377": {
+      topicTags: ["tree", "depth-first-search", "breadth-first-search", "graph"],
+    },
+    "1378": { topicTags: ["database"] },
+    "1379": {
+      topicTags: ["tree", "depth-first-search", "breadth-first-search", "binary-tree"],
+    },
+    "1380": { topicTags: ["array", "matrix"] },
+    "1381": { topicTags: ["stack", "design", "array"] },
+    "1382": {
+      topicTags: ["greedy", "tree", "depth-first-search", "binary-search-tree", "divide-and-conquer", "binary-tree"],
+    },
+    "1383": {
+      topicTags: ["greedy", "array", "sorting", "heap-priority-queue"],
+    },
+    "1384": { topicTags: ["database"] },
+    "1385": {
+      topicTags: ["array", "two-pointers", "binary-search", "sorting"],
+    },
+    "1386": {
+      topicTags: ["greedy", "bit-manipulation", "array", "hash-table"],
+    },
+    "1387": { topicTags: ["memoization", "dynamic-programming", "sorting"] },
+    "1388": {
+      topicTags: ["greedy", "array", "dynamic-programming", "heap-priority-queue"],
+    },
+    "1389": { topicTags: ["array", "simulation"] },
+    "1390": { topicTags: ["array", "math"] },
+    "1391": {
+      topicTags: ["depth-first-search", "breadth-first-search", "union-find", "array", "matrix"],
+    },
+    "1392": {
+      topicTags: ["string", "string-matching", "hash-function", "rolling-hash"],
+    },
+    "1393": { topicTags: ["database"] },
+    "1394": { topicTags: ["array", "hash-table", "counting"] },
+    "1395": {
+      topicTags: ["binary-indexed-tree", "array", "dynamic-programming"],
+    },
+    "1396": { topicTags: ["design", "hash-table", "string"] },
+    "1397": { topicTags: ["string", "dynamic-programming", "string-matching"] },
+    "1398": { topicTags: ["database"] },
+    "1399": { topicTags: ["hash-table", "math"] },
+    "1400": { topicTags: ["greedy", "hash-table", "string", "counting"] },
+    "1401": { topicTags: ["geometry", "math"] },
+    "1402": {
+      topicTags: ["greedy", "array", "dynamic-programming", "sorting"],
+    },
+    "1403": { topicTags: ["greedy", "array", "sorting"] },
+    "1404": { topicTags: ["bit-manipulation", "string"] },
+    "1405": { topicTags: ["greedy", "string", "heap-priority-queue"] },
+    "1406": {
+      topicTags: ["array", "math", "dynamic-programming", "game-theory"],
+    },
+    "1407": { topicTags: ["database"] },
+    "1408": { topicTags: ["string", "string-matching"] },
+    "1409": { topicTags: ["binary-indexed-tree", "array", "simulation"] },
+    "1410": { topicTags: ["hash-table", "string"] },
+    "1411": { topicTags: ["dynamic-programming"] },
+    "1412": { topicTags: ["database"] },
+    "1413": { topicTags: ["array", "prefix-sum"] },
+    "1414": { topicTags: ["greedy"] },
+    "1415": { topicTags: ["string", "backtracking"] },
+    "1416": { topicTags: ["string", "dynamic-programming"] },
+    "1417": { topicTags: ["string"] },
+    "1418": {
+      topicTags: ["array", "hash-table", "string", "ordered-set", "sorting"],
+    },
+    "1419": { topicTags: ["string", "counting"] },
+    "1420": { topicTags: ["dynamic-programming"] },
+    "1421": { topicTags: ["database"] },
+    "1422": { topicTags: ["string"] },
+    "1423": { topicTags: ["array", "prefix-sum", "sliding-window"] },
+    "1424": { topicTags: ["array", "sorting", "heap-priority-queue"] },
+    "1425": {
+      topicTags: ["queue", "array", "dynamic-programming", "sliding-window", "monotonic-queue", "heap-priority-queue"],
+    },
+    "1426": { topicTags: ["array", "hash-table"] },
+    "1427": { topicTags: ["array", "math", "string"] },
+    "1428": { topicTags: ["array", "binary-search", "interactive", "matrix"] },
+    "1429": {
+      topicTags: ["design", "queue", "array", "hash-table", "data-stream"],
+    },
+    "1430": {
+      topicTags: ["tree", "depth-first-search", "breadth-first-search", "binary-tree"],
+    },
+    "1431": { topicTags: ["array"] },
+    "1432": { topicTags: ["greedy", "math"] },
+    "1433": { topicTags: ["greedy", "string", "sorting"] },
+    "1434": {
+      topicTags: ["bit-manipulation", "array", "dynamic-programming", "bitmask"],
+    },
+    "1435": { topicTags: ["database"] },
+    "1436": { topicTags: ["hash-table", "string"] },
+    "1437": { topicTags: ["array"] },
+    "1438": {
+      topicTags: ["queue", "array", "ordered-set", "sliding-window", "monotonic-queue", "heap-priority-queue"],
+    },
+    "1439": {
+      topicTags: ["array", "binary-search", "matrix", "heap-priority-queue"],
+    },
+    "1440": { topicTags: ["database"] },
+    "1441": { topicTags: ["stack", "array", "simulation"] },
+    "1442": {
+      topicTags: ["bit-manipulation", "array", "hash-table", "math", "prefix-sum"],
+    },
+    "1443": {
+      topicTags: ["tree", "depth-first-search", "breadth-first-search", "hash-table"],
+    },
+    "1444": {
+      topicTags: ["memoization", "array", "dynamic-programming", "matrix"],
+    },
+    "1445": { topicTags: ["database"] },
+    "1446": { topicTags: ["string"] },
+    "1447": { topicTags: ["math", "string", "number-theory"] },
+    "1448": {
+      topicTags: ["tree", "depth-first-search", "breadth-first-search", "binary-tree"],
+    },
+    "1449": { topicTags: ["array", "dynamic-programming"] },
+    "1450": { topicTags: ["array"] },
+    "1451": { topicTags: ["string", "sorting"] },
+    "1452": { topicTags: ["array", "hash-table", "string"] },
+    "1453": { topicTags: ["geometry", "array", "math"] },
+    "1454": { topicTags: ["database"] },
+    "1455": { topicTags: ["string", "string-matching"] },
+    "1456": { topicTags: ["string", "sliding-window"] },
+    "1457": {
+      topicTags: ["bit-manipulation", "tree", "depth-first-search", "breadth-first-search", "binary-tree"],
+    },
+    "1458": { topicTags: ["array", "dynamic-programming"] },
+    "1459": { topicTags: ["database"] },
+    "1460": { topicTags: ["array", "hash-table", "sorting"] },
+    "1461": {
+      topicTags: ["bit-manipulation", "hash-table", "string", "hash-function", "rolling-hash"],
+    },
+    "1462": {
+      topicTags: ["depth-first-search", "breadth-first-search", "graph", "topological-sort"],
+    },
+    "1463": { topicTags: ["array", "dynamic-programming", "matrix"] },
+    "1464": { topicTags: ["array", "sorting", "heap-priority-queue"] },
+    "1465": { topicTags: ["greedy", "array", "sorting"] },
+    "1466": {
+      topicTags: ["depth-first-search", "breadth-first-search", "graph"],
+    },
+    "1467": {
+      topicTags: ["math", "dynamic-programming", "backtracking", "combinatorics", "probability-and-statistics"],
+    },
+    "1468": { topicTags: ["database"] },
+    "1469": {
+      topicTags: ["tree", "depth-first-search", "breadth-first-search", "binary-tree"],
+    },
+    "1470": { topicTags: ["array"] },
+    "1471": { topicTags: ["array", "two-pointers", "sorting"] },
+    "1472": {
+      topicTags: ["stack", "design", "array", "linked-list", "data-stream", "doubly-linked-list"],
+    },
+    "1473": { topicTags: ["array", "dynamic-programming"] },
+    "1474": { topicTags: ["linked-list"] },
+    "1475": { topicTags: ["stack", "array", "monotonic-stack"] },
+    "1476": { topicTags: ["design", "array", "matrix"] },
+    "1477": {
+      topicTags: ["array", "hash-table", "binary-search", "dynamic-programming", "sliding-window"],
+    },
+    "1478": { topicTags: ["array", "math", "dynamic-programming", "sorting"] },
+    "1479": { topicTags: ["database"] },
+    "1480": { topicTags: ["array", "prefix-sum"] },
+    "1481": {
+      topicTags: ["greedy", "array", "hash-table", "counting", "sorting"],
+    },
+    "1482": { topicTags: ["array", "binary-search"] },
+    "1483": {
+      topicTags: [
+        "tree",
+        "depth-first-search",
+        "breadth-first-search",
+        "design",
+        "binary-search",
+        "dynamic-programming",
+      ],
+    },
+    "1484": { topicTags: ["database"] },
+    "1485": {
+      topicTags: ["tree", "depth-first-search", "breadth-first-search", "hash-table", "binary-tree"],
+    },
+    "1486": { topicTags: ["bit-manipulation", "math"] },
+    "1487": { topicTags: ["array", "hash-table", "string"] },
+    "1488": {
+      topicTags: ["greedy", "array", "hash-table", "binary-search", "heap-priority-queue"],
+    },
+    "1489": {
+      topicTags: ["union-find", "graph", "minimum-spanning-tree", "sorting", "strongly-connected-component"],
+    },
+    "1490": {
+      topicTags: ["tree", "depth-first-search", "breadth-first-search", "hash-table"],
+    },
+    "1491": { topicTags: ["array", "sorting"] },
+    "1492": { topicTags: ["math"] },
+    "1493": { topicTags: ["array", "dynamic-programming", "sliding-window"] },
+    "1494": {
+      topicTags: ["bit-manipulation", "graph", "dynamic-programming", "bitmask"],
+    },
+    "1495": { topicTags: ["database"] },
+    "1496": { topicTags: ["hash-table", "string"] },
+    "1497": { topicTags: ["array", "hash-table", "counting"] },
+    "1498": {
+      topicTags: ["array", "two-pointers", "binary-search", "sorting"],
+    },
+    "1499": {
+      topicTags: ["queue", "array", "sliding-window", "monotonic-queue", "heap-priority-queue"],
+    },
+    "1500": {
+      topicTags: ["design", "hash-table", "data-stream", "heap-priority-queue"],
+    },
+    "1501": { topicTags: ["database"] },
+    "1502": { topicTags: ["array", "sorting"] },
+    "1503": { topicTags: ["brainteaser", "array", "simulation"] },
+    "1504": {
+      topicTags: ["stack", "array", "dynamic-programming", "matrix", "monotonic-stack"],
+    },
+    "1505": {
+      topicTags: ["greedy", "binary-indexed-tree", "segment-tree", "string"],
+    },
+    "1506": {
+      topicTags: ["bit-manipulation", "tree", "depth-first-search", "hash-table"],
+    },
+    "1507": { topicTags: ["string"] },
+    "1508": {
+      topicTags: ["array", "two-pointers", "binary-search", "sorting"],
+    },
+    "1509": { topicTags: ["greedy", "array", "sorting"] },
+    "1510": { topicTags: ["math", "dynamic-programming", "game-theory"] },
+    "1511": { topicTags: ["database"] },
+    "1512": { topicTags: ["array", "hash-table", "math", "counting"] },
+    "1513": { topicTags: ["math", "string"] },
+    "1514": { topicTags: ["graph", "shortest-path", "heap-priority-queue"] },
+    "1515": { topicTags: ["geometry", "math", "randomized"] },
+    "1516": { topicTags: ["tree", "depth-first-search"] },
+    "1517": { topicTags: ["database"] },
+    "1518": { topicTags: ["math", "simulation"] },
+    "1519": {
+      topicTags: ["tree", "depth-first-search", "breadth-first-search", "hash-table", "counting"],
+    },
+    "1520": { topicTags: ["greedy", "string"] },
+    "1521": {
+      topicTags: ["bit-manipulation", "segment-tree", "array", "binary-search"],
+    },
+    "1522": { topicTags: ["tree", "depth-first-search"] },
+    "1523": { topicTags: ["math"] },
+    "1524": {
+      topicTags: ["array", "math", "dynamic-programming", "prefix-sum"],
+    },
+    "1525": {
+      topicTags: ["bit-manipulation", "string", "dynamic-programming"],
+    },
+    "1526": {
+      topicTags: ["stack", "greedy", "array", "dynamic-programming", "monotonic-stack"],
+    },
+    "1527": { topicTags: ["database"] },
+    "1528": { topicTags: ["array", "string"] },
+    "1529": { topicTags: ["greedy", "string"] },
+    "1530": { topicTags: ["tree", "depth-first-search", "binary-tree"] },
+    "1531": { topicTags: ["string", "dynamic-programming"] },
+    "1532": { topicTags: ["database"] },
+    "1533": { topicTags: ["array", "binary-search", "interactive"] },
+    "1534": { topicTags: ["array", "enumeration"] },
+    "1535": { topicTags: ["array", "simulation"] },
+    "1536": { topicTags: ["greedy", "array", "matrix"] },
+    "1537": {
+      topicTags: ["greedy", "array", "two-pointers", "dynamic-programming"],
+    },
+    "1538": { topicTags: ["array", "math", "interactive"] },
+    "1539": { topicTags: ["array", "binary-search"] },
+    "1540": { topicTags: ["hash-table", "string"] },
+    "1541": { topicTags: ["stack", "greedy", "string"] },
+    "1542": { topicTags: ["bit-manipulation", "hash-table", "string"] },
+    "1543": { topicTags: ["database"] },
+    "1544": { topicTags: ["stack", "string"] },
+    "1545": { topicTags: ["recursion", "string"] },
+    "1546": { topicTags: ["greedy", "array", "hash-table", "prefix-sum"] },
+    "1547": { topicTags: ["array", "dynamic-programming"] },
+    "1548": { topicTags: ["graph", "dynamic-programming"] },
+    "1549": { topicTags: ["database"] },
+    "1550": { topicTags: ["array"] },
+    "1551": { topicTags: ["math"] },
+    "1552": { topicTags: ["array", "binary-search", "sorting"] },
+    "1553": { topicTags: ["memoization", "dynamic-programming"] },
+    "1554": {
+      topicTags: ["hash-table", "string", "hash-function", "rolling-hash"],
+    },
+    "1555": { topicTags: ["database"] },
+    "1556": { topicTags: ["string"] },
+    "1557": { topicTags: ["graph"] },
+    "1558": { topicTags: ["greedy", "array"] },
+    "1559": {
+      topicTags: ["depth-first-search", "breadth-first-search", "union-find", "array", "matrix"],
+    },
+    "1560": { topicTags: ["array", "simulation"] },
+    "1561": {
+      topicTags: ["greedy", "array", "math", "game-theory", "sorting"],
+    },
+    "1562": { topicTags: ["array", "binary-search", "simulation"] },
+    "1563": {
+      topicTags: ["array", "math", "dynamic-programming", "game-theory"],
+    },
+    "1564": { topicTags: ["greedy", "array", "sorting"] },
+    "1565": { topicTags: ["database"] },
+    "1566": { topicTags: ["array", "enumeration"] },
+    "1567": { topicTags: ["greedy", "array", "dynamic-programming"] },
+    "1568": {
+      topicTags: ["depth-first-search", "breadth-first-search", "array", "matrix", "strongly-connected-component"],
+    },
+    "1569": {
+      topicTags: [
+        "tree",
+        "union-find",
+        "binary-search-tree",
+        "memoization",
+        "array",
+        "math",
+        "divide-and-conquer",
+        "dynamic-programming",
+        "binary-tree",
+        "combinatorics",
+      ],
+    },
+    "1570": { topicTags: ["design", "array", "hash-table", "two-pointers"] },
+    "1571": { topicTags: ["database"] },
+    "1572": { topicTags: ["array", "matrix"] },
+    "1573": { topicTags: ["math", "string"] },
+    "1574": {
+      topicTags: ["stack", "array", "two-pointers", "binary-search", "monotonic-stack"],
+    },
+    "1575": { topicTags: ["memoization", "array", "dynamic-programming"] },
+    "1576": { topicTags: ["string"] },
+    "1577": { topicTags: ["array", "hash-table", "math", "two-pointers"] },
+    "1578": { topicTags: ["greedy", "array", "string", "dynamic-programming"] },
+    "1579": { topicTags: ["union-find", "graph"] },
+    "1580": { topicTags: ["greedy", "array", "sorting"] },
+    "1581": { topicTags: ["database"] },
+    "1582": { topicTags: ["array", "matrix"] },
+    "1583": { topicTags: ["array", "simulation"] },
+    "1584": { topicTags: ["union-find", "array", "minimum-spanning-tree"] },
+    "1585": { topicTags: ["greedy", "string", "sorting"] },
+    "1586": {
+      topicTags: ["stack", "tree", "design", "binary-search-tree", "binary-tree", "iterator"],
+    },
+    "1587": { topicTags: ["database"] },
+    "1588": { topicTags: ["array", "math", "prefix-sum"] },
+    "1589": { topicTags: ["greedy", "array", "prefix-sum", "sorting"] },
+    "1590": { topicTags: ["array", "hash-table", "prefix-sum"] },
+    "1591": { topicTags: ["graph", "topological-sort", "array", "matrix"] },
+    "1592": { topicTags: ["string"] },
+    "1593": { topicTags: ["hash-table", "string", "backtracking"] },
+    "1594": { topicTags: ["array", "dynamic-programming", "matrix"] },
+    "1595": {
+      topicTags: ["bit-manipulation", "array", "dynamic-programming", "bitmask", "matrix"],
+    },
+    "1596": { topicTags: ["database"] },
+    "1597": { topicTags: ["stack", "tree", "string", "binary-tree"] },
+    "1598": { topicTags: ["stack", "array", "string"] },
+    "1599": { topicTags: ["array", "simulation"] },
+    "1600": {
+      topicTags: ["tree", "depth-first-search", "design", "hash-table"],
+    },
+    "1601": {
+      topicTags: ["bit-manipulation", "array", "backtracking", "enumeration"],
+    },
+    "1602": { topicTags: ["tree", "breadth-first-search", "binary-tree"] },
+    "1603": { topicTags: ["design", "counting", "simulation"] },
+    "1604": { topicTags: ["array", "hash-table", "string", "sorting"] },
+    "1605": { topicTags: ["greedy", "array", "matrix"] },
+    "1606": {
+      topicTags: ["greedy", "array", "ordered-set", "heap-priority-queue"],
+    },
+    "1607": { topicTags: ["database"] },
+    "1608": { topicTags: ["array", "binary-search", "sorting"] },
+    "1609": { topicTags: ["tree", "breadth-first-search", "binary-tree"] },
+    "1610": {
+      topicTags: ["geometry", "array", "math", "sorting", "sliding-window"],
+    },
+    "1611": {
+      topicTags: ["bit-manipulation", "memoization", "dynamic-programming"],
+    },
+    "1612": { topicTags: ["tree", "depth-first-search", "binary-tree"] },
+    "1613": { topicTags: ["database"] },
+    "1614": { topicTags: ["stack", "string"] },
+    "1615": { topicTags: ["graph"] },
+    "1616": { topicTags: ["two-pointers", "string"] },
+    "1617": {
+      topicTags: ["bit-manipulation", "tree", "dynamic-programming", "bitmask", "enumeration"],
+    },
+    "1618": { topicTags: ["array", "string", "binary-search", "interactive"] },
+    "1619": { topicTags: ["array", "sorting"] },
+    "1620": { topicTags: ["array", "enumeration"] },
+    "1621": { topicTags: ["math", "dynamic-programming"] },
+    "1622": { topicTags: ["design", "segment-tree", "math"] },
+    "1623": { topicTags: ["database"] },
+    "1624": { topicTags: ["hash-table", "string"] },
+    "1625": { topicTags: ["breadth-first-search", "string"] },
+    "1626": { topicTags: ["array", "dynamic-programming", "sorting"] },
+    "1627": { topicTags: ["union-find", "array", "math"] },
+    "1628": { topicTags: ["stack", "tree", "design", "math", "binary-tree"] },
+    "1629": { topicTags: ["array", "string"] },
+    "1630": { topicTags: ["array", "sorting"] },
+    "1631": {
+      topicTags: [
+        "depth-first-search",
+        "breadth-first-search",
+        "union-find",
+        "array",
+        "binary-search",
+        "matrix",
+        "heap-priority-queue",
+      ],
+    },
+    "1632": {
+      topicTags: ["greedy", "union-find", "graph", "topological-sort", "array", "matrix"],
+    },
+    "1633": { topicTags: ["database"] },
+    "1634": { topicTags: ["linked-list", "math", "two-pointers"] },
+    "1635": { topicTags: ["database"] },
+    "1636": { topicTags: ["array", "hash-table", "sorting"] },
+    "1637": { topicTags: ["array", "sorting"] },
+    "1638": { topicTags: ["hash-table", "string", "dynamic-programming"] },
+    "1639": { topicTags: ["array", "string", "dynamic-programming"] },
+    "1640": { topicTags: ["array", "hash-table"] },
+    "1641": { topicTags: ["dynamic-programming"] },
+    "1642": { topicTags: ["greedy", "array", "heap-priority-queue"] },
+    "1643": {
+      topicTags: ["array", "math", "dynamic-programming", "combinatorics"],
+    },
+    "1644": { topicTags: ["tree", "depth-first-search", "binary-tree"] },
+    "1645": { topicTags: ["database"] },
+    "1646": { topicTags: ["array", "dynamic-programming", "simulation"] },
+    "1647": { topicTags: ["greedy", "string", "sorting"] },
+    "1648": {
+      topicTags: ["greedy", "array", "math", "binary-search", "sorting", "heap-priority-queue"],
+    },
+    "1649": {
+      topicTags: [
+        "binary-indexed-tree",
+        "segment-tree",
+        "array",
+        "binary-search",
+        "divide-and-conquer",
+        "ordered-set",
+        "merge-sort",
+      ],
+    },
+    "1650": { topicTags: ["tree", "hash-table", "binary-tree"] },
+    "1651": { topicTags: ["database"] },
+    "1652": { topicTags: ["array"] },
+    "1653": { topicTags: ["stack", "string", "dynamic-programming"] },
+    "1654": {
+      topicTags: ["breadth-first-search", "array", "dynamic-programming"],
+    },
+    "1655": {
+      topicTags: ["bit-manipulation", "array", "dynamic-programming", "backtracking", "bitmask"],
+    },
+    "1656": { topicTags: ["design", "array", "hash-table", "data-stream"] },
+    "1657": { topicTags: ["hash-table", "string", "sorting"] },
+    "1658": {
+      topicTags: ["array", "hash-table", "binary-search", "prefix-sum", "sliding-window"],
+    },
+    "1659": {
+      topicTags: ["bit-manipulation", "memoization", "dynamic-programming", "bitmask"],
+    },
+    "1660": {
+      topicTags: ["tree", "depth-first-search", "breadth-first-search", "hash-table", "binary-tree"],
+    },
+    "1661": { topicTags: ["database"] },
+    "1662": { topicTags: ["array", "string"] },
+    "1663": { topicTags: ["greedy", "string"] },
+    "1664": { topicTags: ["array", "dynamic-programming"] },
+    "1665": { topicTags: ["greedy", "array", "sorting"] },
+    "1666": { topicTags: ["tree", "depth-first-search", "binary-tree"] },
+    "1667": { topicTags: ["database"] },
+    "1668": { topicTags: ["string", "string-matching"] },
+    "1669": { topicTags: ["linked-list"] },
+    "1670": {
+      topicTags: ["design", "queue", "array", "linked-list", "data-stream"],
+    },
+    "1671": {
+      topicTags: ["greedy", "array", "binary-search", "dynamic-programming"],
+    },
+    "1672": { topicTags: ["array", "matrix"] },
+    "1673": { topicTags: ["stack", "greedy", "array", "monotonic-stack"] },
+    "1674": { topicTags: ["array", "hash-table", "prefix-sum"] },
+    "1675": {
+      topicTags: ["greedy", "array", "ordered-set", "heap-priority-queue"],
+    },
+    "1676": { topicTags: ["tree", "depth-first-search", "binary-tree"] },
+    "1677": { topicTags: ["database"] },
+    "1678": { topicTags: ["string"] },
+    "1679": { topicTags: ["array", "hash-table", "two-pointers", "sorting"] },
+    "1680": { topicTags: ["bit-manipulation", "math", "simulation"] },
+    "1681": {
+      topicTags: ["bit-manipulation", "array", "dynamic-programming", "bitmask"],
+    },
+    "1682": { topicTags: ["string", "dynamic-programming"] },
+    "1683": { topicTags: ["database"] },
+    "1684": {
+      topicTags: ["bit-manipulation", "array", "hash-table", "string"],
+    },
+    "1685": { topicTags: ["array", "math", "prefix-sum"] },
+    "1686": {
+      topicTags: ["greedy", "array", "math", "game-theory", "sorting", "heap-priority-queue"],
+    },
+    "1687": {
+      topicTags: ["segment-tree", "queue", "array", "dynamic-programming", "monotonic-queue", "heap-priority-queue"],
+    },
+    "1688": { topicTags: ["math", "simulation"] },
+    "1689": { topicTags: ["greedy", "string"] },
+    "1690": {
+      topicTags: ["array", "math", "dynamic-programming", "game-theory"],
+    },
+    "1691": { topicTags: ["array", "dynamic-programming", "sorting"] },
+    "1692": { topicTags: ["dynamic-programming"] },
+    "1693": { topicTags: ["database"] },
+    "1694": { topicTags: ["string"] },
+    "1695": { topicTags: ["array", "hash-table", "sliding-window"] },
+    "1696": {
+      topicTags: ["queue", "array", "dynamic-programming", "sliding-window", "monotonic-queue", "heap-priority-queue"],
+    },
+    "1697": { topicTags: ["union-find", "graph", "array", "sorting"] },
+    "1698": {
+      topicTags: ["trie", "string", "suffix-array", "hash-function", "rolling-hash"],
+    },
+    "1699": { topicTags: ["database"] },
+    "1700": { topicTags: ["stack", "queue", "array", "simulation"] },
+    "1701": { topicTags: ["array", "simulation"] },
+    "1702": { topicTags: ["greedy", "string"] },
+    "1703": { topicTags: ["greedy", "array", "prefix-sum", "sliding-window"] },
+    "1704": { topicTags: ["string", "counting"] },
+    "1705": { topicTags: ["greedy", "array", "heap-priority-queue"] },
+    "1706": {
+      topicTags: ["depth-first-search", "array", "dynamic-programming", "matrix", "simulation"],
+    },
+    "1707": { topicTags: ["bit-manipulation", "trie", "array"] },
+    "1708": { topicTags: ["greedy", "array"] },
+    "1709": { topicTags: ["database"] },
+    "1710": { topicTags: ["greedy", "array", "sorting"] },
+    "1711": { topicTags: ["array", "hash-table"] },
+    "1712": {
+      topicTags: ["array", "two-pointers", "binary-search", "prefix-sum"],
+    },
+    "1713": { topicTags: ["greedy", "array", "hash-table", "binary-search"] },
+    "1714": { topicTags: ["array", "dynamic-programming"] },
+    "1715": { topicTags: ["database"] },
+    "1716": { topicTags: ["math"] },
+    "1717": { topicTags: ["stack", "greedy", "string"] },
+    "1718": { topicTags: ["array", "backtracking"] },
+    "1719": { topicTags: ["tree", "graph", "topological-sort"] },
+    "1720": { topicTags: ["bit-manipulation", "array"] },
+    "1721": { topicTags: ["linked-list", "two-pointers"] },
+    "1722": { topicTags: ["depth-first-search", "union-find", "array"] },
+    "1723": {
+      topicTags: ["bit-manipulation", "array", "dynamic-programming", "backtracking", "bitmask"],
+    },
+    "1724": { topicTags: ["union-find", "graph", "minimum-spanning-tree"] },
+    "1725": { topicTags: ["array"] },
+    "1726": { topicTags: ["array", "hash-table"] },
+    "1727": { topicTags: ["greedy", "array", "matrix", "sorting"] },
+    "1728": {
+      topicTags: [
+        "graph",
+        "topological-sort",
+        "memoization",
+        "array",
+        "math",
+        "dynamic-programming",
+        "game-theory",
+        "matrix",
+      ],
+    },
+    "1729": { topicTags: ["database"] },
+    "1730": { topicTags: ["breadth-first-search", "array", "matrix"] },
+    "1731": { topicTags: ["database"] },
+    "1732": { topicTags: ["array", "prefix-sum"] },
+    "1733": { topicTags: ["greedy", "array"] },
+    "1734": { topicTags: ["bit-manipulation", "array"] },
+    "1735": {
+      topicTags: ["array", "math", "dynamic-programming", "combinatorics", "number-theory"],
+    },
+    "1736": { topicTags: ["string"] },
+    "1737": { topicTags: ["hash-table", "string", "counting", "prefix-sum"] },
+    "1738": {
+      topicTags: [
+        "bit-manipulation",
+        "array",
+        "divide-and-conquer",
+        "matrix",
+        "prefix-sum",
+        "quickselect",
+        "heap-priority-queue",
+      ],
+    },
+    "1739": { topicTags: ["greedy", "math", "binary-search"] },
+    "1740": {
+      topicTags: ["tree", "depth-first-search", "breadth-first-search", "hash-table", "binary-tree"],
+    },
+    "1741": { topicTags: ["database"] },
+    "1742": { topicTags: ["hash-table", "math", "counting"] },
+    "1743": { topicTags: ["array", "hash-table"] },
+    "1744": { topicTags: ["array", "prefix-sum"] },
+    "1745": { topicTags: ["string", "dynamic-programming"] },
+    "1746": { topicTags: ["array", "dynamic-programming"] },
+    "1747": { topicTags: ["database"] },
+    "1748": { topicTags: ["array", "hash-table", "counting"] },
+    "1749": { topicTags: ["array", "dynamic-programming"] },
+    "1750": { topicTags: ["two-pointers", "string"] },
+    "1751": { topicTags: ["array", "binary-search", "dynamic-programming"] },
+    "1752": { topicTags: ["array"] },
+    "1753": { topicTags: ["greedy", "math", "heap-priority-queue"] },
+    "1754": { topicTags: ["greedy", "two-pointers", "string"] },
+    "1755": {
+      topicTags: ["bit-manipulation", "array", "two-pointers", "dynamic-programming", "bitmask"],
+    },
+    "1756": {
+      topicTags: ["stack", "design", "binary-indexed-tree", "array", "hash-table", "ordered-set"],
+    },
+    "1757": { topicTags: ["database"] },
+    "1758": { topicTags: ["string"] },
+    "1759": { topicTags: ["math", "string"] },
+    "1760": { topicTags: ["array", "binary-search"] },
+    "1761": { topicTags: ["graph"] },
+    "1762": { topicTags: ["stack", "array", "monotonic-stack"] },
+    "1763": {
+      topicTags: ["bit-manipulation", "hash-table", "string", "divide-and-conquer", "sliding-window"],
+    },
+    "1764": { topicTags: ["greedy", "array", "string-matching"] },
+    "1765": { topicTags: ["breadth-first-search", "array", "matrix"] },
+    "1766": {
+      topicTags: ["tree", "depth-first-search", "breadth-first-search", "math"],
+    },
+    "1767": { topicTags: ["database"] },
+    "1768": { topicTags: ["two-pointers", "string"] },
+    "1769": { topicTags: ["array", "string"] },
+    "1770": { topicTags: ["array", "dynamic-programming"] },
+    "1771": { topicTags: ["string", "dynamic-programming"] },
+    "1772": { topicTags: ["array", "hash-table", "string", "sorting"] },
+    "1773": { topicTags: ["array", "string"] },
+    "1774": { topicTags: ["array", "dynamic-programming", "backtracking"] },
+    "1775": { topicTags: ["greedy", "array", "hash-table", "counting"] },
+    "1776": {
+      topicTags: ["stack", "array", "math", "monotonic-stack", "heap-priority-queue"],
+    },
+    "1777": { topicTags: ["database"] },
+    "1778": {
+      topicTags: ["depth-first-search", "breadth-first-search", "graph", "interactive"],
+    },
+    "1779": { topicTags: ["array"] },
+    "1780": { topicTags: ["math"] },
+    "1781": { topicTags: ["hash-table", "string", "counting"] },
+    "1782": { topicTags: ["graph", "two-pointers", "binary-search"] },
+    "1783": { topicTags: ["database"] },
+    "1784": { topicTags: ["string"] },
+    "1785": { topicTags: ["greedy", "array"] },
+    "1786": {
+      topicTags: ["graph", "topological-sort", "dynamic-programming", "shortest-path", "heap-priority-queue"],
+    },
+    "1787": { topicTags: ["bit-manipulation", "array", "dynamic-programming"] },
+    "1788": { topicTags: ["greedy", "array", "prefix-sum"] },
+    "1789": { topicTags: ["database"] },
+    "1790": { topicTags: ["hash-table", "string", "counting"] },
+    "1791": { topicTags: ["graph"] },
+    "1792": { topicTags: ["greedy", "array", "heap-priority-queue"] },
+    "1793": {
+      topicTags: ["stack", "array", "two-pointers", "binary-search", "monotonic-stack"],
+    },
+    "1794": { topicTags: ["greedy", "hash-table", "string"] },
+    "1795": { topicTags: ["database"] },
+    "1796": { topicTags: ["hash-table", "string"] },
+    "1797": { topicTags: ["design", "hash-table"] },
+    "1798": { topicTags: ["greedy", "array"] },
+    "1799": {
+      topicTags: [
+        "bit-manipulation",
+        "array",
+        "math",
+        "dynamic-programming",
+        "backtracking",
+        "bitmask",
+        "number-theory",
+      ],
+    },
+    "1800": { topicTags: ["array"] },
+    "1801": { topicTags: ["array", "simulation", "heap-priority-queue"] },
+    "1802": { topicTags: ["greedy", "binary-search"] },
+    "1803": { topicTags: ["bit-manipulation", "trie", "array"] },
+    "1804": { topicTags: ["design", "trie", "hash-table", "string"] },
+    "1805": { topicTags: ["hash-table", "string"] },
+    "1806": { topicTags: ["array", "math", "simulation"] },
+    "1807": { topicTags: ["array", "hash-table", "string"] },
+    "1808": { topicTags: ["recursion", "math"] },
+    "1809": { topicTags: ["database"] },
+    "1810": {
+      topicTags: ["depth-first-search", "breadth-first-search", "graph", "interactive", "heap-priority-queue"],
+    },
+    "1811": { topicTags: ["database"] },
+    "1812": { topicTags: ["math", "string"] },
+    "1813": { topicTags: ["array", "two-pointers", "string"] },
+    "1814": { topicTags: ["array", "hash-table", "math", "counting"] },
+    "1815": {
+      topicTags: ["bit-manipulation", "memoization", "array", "dynamic-programming", "bitmask"],
+    },
+    "1816": { topicTags: ["array", "string"] },
+    "1817": { topicTags: ["array", "hash-table"] },
+    "1818": { topicTags: ["array", "binary-search", "ordered-set", "sorting"] },
+    "1819": { topicTags: ["array", "math", "counting", "number-theory"] },
+    "1820": { topicTags: ["array", "backtracking", "matrix"] },
+    "1821": { topicTags: ["database"] },
+    "1822": { topicTags: ["array", "math"] },
+    "1823": {
+      topicTags: ["recursion", "queue", "array", "math", "simulation"],
+    },
+    "1824": { topicTags: ["greedy", "array", "dynamic-programming"] },
+    "1825": {
+      topicTags: ["design", "queue", "data-stream", "ordered-set", "heap-priority-queue"],
+    },
+    "1826": { topicTags: ["array", "two-pointers"] },
+    "1827": { topicTags: ["greedy", "array"] },
+    "1828": { topicTags: ["geometry", "array", "math"] },
+    "1829": { topicTags: ["bit-manipulation", "array", "prefix-sum"] },
+    "1830": { topicTags: ["math", "string", "combinatorics"] },
+    "1831": { topicTags: ["database"] },
+    "1832": { topicTags: ["hash-table", "string"] },
+    "1833": { topicTags: ["greedy", "array", "sorting"] },
+    "1834": { topicTags: ["array", "sorting", "heap-priority-queue"] },
+    "1835": { topicTags: ["bit-manipulation", "array", "math"] },
+    "1836": { topicTags: ["hash-table", "linked-list"] },
+    "1837": { topicTags: ["math"] },
+    "1838": {
+      topicTags: ["array", "binary-search", "prefix-sum", "sliding-window"],
+    },
+    "1839": { topicTags: ["string", "sliding-window"] },
+    "1840": { topicTags: ["array", "math"] },
+    "1841": { topicTags: ["database"] },
+    "1842": { topicTags: ["two-pointers", "string"] },
+    "1843": { topicTags: ["database"] },
+    "1844": { topicTags: ["string"] },
+    "1845": { topicTags: ["design", "heap-priority-queue"] },
+    "1846": { topicTags: ["greedy", "array", "sorting"] },
+    "1847": { topicTags: ["array", "binary-search", "sorting"] },
+    "1848": { topicTags: ["array"] },
+    "1849": { topicTags: ["string", "backtracking"] },
+    "1850": { topicTags: ["greedy", "two-pointers", "string"] },
+    "1851": {
+      topicTags: ["array", "binary-search", "sorting", "line-sweep", "heap-priority-queue"],
+    },
+    "1852": { topicTags: ["array", "hash-table", "sliding-window"] },
+    "1853": { topicTags: ["database"] },
+    "1854": { topicTags: ["array", "counting"] },
+    "1855": { topicTags: ["greedy", "array", "two-pointers", "binary-search"] },
+    "1856": { topicTags: ["stack", "array", "prefix-sum", "monotonic-stack"] },
+    "1857": {
+      topicTags: ["graph", "topological-sort", "memoization", "hash-table", "dynamic-programming", "counting"],
+    },
+    "1858": { topicTags: ["depth-first-search", "trie"] },
+    "1859": { topicTags: ["string", "sorting"] },
+    "1860": { topicTags: ["simulation"] },
+    "1861": { topicTags: ["array", "two-pointers", "matrix"] },
+    "1862": { topicTags: ["array", "math", "binary-search", "prefix-sum"] },
+    "1863": {
+      topicTags: ["bit-manipulation", "array", "math", "backtracking", "combinatorics"],
+    },
+    "1864": { topicTags: ["greedy", "string"] },
+    "1865": { topicTags: ["design", "array", "hash-table"] },
+    "1866": { topicTags: ["math", "dynamic-programming", "combinatorics"] },
+    "1867": { topicTags: ["database"] },
+    "1868": { topicTags: ["array", "two-pointers"] },
+    "1869": { topicTags: ["string"] },
+    "1870": { topicTags: ["array", "binary-search"] },
+    "1871": { topicTags: ["two-pointers", "string", "prefix-sum"] },
+    "1872": {
+      topicTags: ["array", "math", "dynamic-programming", "game-theory", "prefix-sum"],
+    },
+    "1873": { topicTags: ["database"] },
+    "1874": { topicTags: ["greedy", "array", "sorting"] },
+    "1875": { topicTags: ["database"] },
+    "1876": {
+      topicTags: ["hash-table", "string", "counting", "sliding-window"],
+    },
+    "1877": { topicTags: ["greedy", "array", "two-pointers", "sorting"] },
+    "1878": {
+      topicTags: ["array", "math", "matrix", "prefix-sum", "sorting", "heap-priority-queue"],
+    },
+    "1879": {
+      topicTags: ["bit-manipulation", "array", "dynamic-programming", "bitmask"],
+    },
+    "1880": { topicTags: ["string"] },
+    "1881": { topicTags: ["greedy", "string"] },
+    "1882": { topicTags: ["array", "heap-priority-queue"] },
+    "1883": { topicTags: ["array", "dynamic-programming"] },
+    "1884": { topicTags: ["math", "dynamic-programming"] },
+    "1885": { topicTags: ["array", "binary-search", "sorting"] },
+    "1886": { topicTags: ["array", "matrix"] },
+    "1887": { topicTags: ["array", "sorting"] },
+    "1888": {
+      topicTags: ["greedy", "string", "dynamic-programming", "sliding-window"],
+    },
+    "1889": { topicTags: ["array", "binary-search", "prefix-sum", "sorting"] },
+    "1890": { topicTags: ["database"] },
+    "1891": { topicTags: ["array", "binary-search"] },
+    "1892": { topicTags: ["database"] },
+    "1893": { topicTags: ["array", "hash-table", "prefix-sum"] },
+    "1894": {
+      topicTags: ["array", "binary-search", "prefix-sum", "simulation"],
+    },
+    "1895": { topicTags: ["array", "matrix", "prefix-sum"] },
+    "1896": { topicTags: ["stack", "math", "string", "dynamic-programming"] },
+    "1897": { topicTags: ["hash-table", "string", "counting"] },
+    "1898": { topicTags: ["array", "string", "binary-search"] },
+    "1899": { topicTags: ["greedy", "array"] },
+    "1900": { topicTags: ["memoization", "dynamic-programming"] },
+    "1901": { topicTags: ["array", "binary-search", "matrix"] },
+    "1902": {
+      topicTags: ["tree", "binary-search-tree", "binary-tree", "ordered-set"],
+    },
+    "1903": { topicTags: ["greedy", "math", "string"] },
+    "1904": { topicTags: ["math", "string"] },
+    "1905": {
+      topicTags: ["depth-first-search", "breadth-first-search", "union-find", "array", "matrix"],
+    },
+    "1906": { topicTags: ["array", "hash-table"] },
+    "1907": { topicTags: ["database"] },
+    "1908": {
+      topicTags: ["bit-manipulation", "brainteaser", "array", "math", "dynamic-programming", "game-theory"],
+    },
+    "1909": { topicTags: ["array"] },
+    "1910": { topicTags: ["string"] },
+    "1911": { topicTags: ["array", "dynamic-programming"] },
+    "1912": {
+      topicTags: ["design", "array", "hash-table", "ordered-set", "heap-priority-queue"],
+    },
+    "1913": { topicTags: ["array", "sorting"] },
+    "1914": { topicTags: ["array", "matrix", "simulation"] },
+    "1915": {
+      topicTags: ["bit-manipulation", "hash-table", "string", "prefix-sum"],
+    },
+    "1916": {
+      topicTags: ["tree", "graph", "topological-sort", "math", "dynamic-programming", "combinatorics"],
+    },
+    "1917": { topicTags: ["database"] },
+    "1918": { topicTags: ["array", "binary-search", "sliding-window"] },
+    "1919": { topicTags: ["database"] },
+    "1920": { topicTags: ["array", "simulation"] },
+    "1921": { topicTags: ["greedy", "array", "sorting"] },
+    "1922": { topicTags: ["recursion", "math"] },
+    "1923": {
+      topicTags: ["array", "binary-search", "suffix-array", "hash-function", "rolling-hash"],
+    },
+    "1924": { topicTags: ["geometry", "array", "math"] },
+    "1925": { topicTags: ["math", "enumeration"] },
+    "1926": { topicTags: ["breadth-first-search", "array", "matrix"] },
+    "1927": { topicTags: ["greedy", "math", "game-theory"] },
+    "1928": { topicTags: ["graph", "dynamic-programming"] },
+    "1929": { topicTags: ["array"] },
+    "1930": { topicTags: ["hash-table", "string", "prefix-sum"] },
+    "1931": { topicTags: ["dynamic-programming"] },
+    "1932": {
+      topicTags: ["tree", "depth-first-search", "hash-table", "binary-search", "binary-tree"],
+    },
+    "1933": { topicTags: ["string"] },
+    "1934": { topicTags: ["database"] },
+    "1935": { topicTags: ["hash-table", "string"] },
+    "1936": { topicTags: ["greedy", "array"] },
+    "1937": { topicTags: [] },
+    "1938": { topicTags: [] },
+    "1939": { topicTags: ["database"] },
+    "1940": { topicTags: ["array", "hash-table", "counting"] },
+    "1941": { topicTags: ["hash-table", "string", "counting"] },
+    "1942": { topicTags: ["array", "ordered-set", "heap-priority-queue"] },
+    "1943": { topicTags: ["array", "prefix-sum"] },
+    "1944": { topicTags: ["stack", "array", "monotonic-stack"] },
+    "1945": { topicTags: ["string", "simulation"] },
+    "1946": { topicTags: ["greedy", "array", "string"] },
+    "1947": {
+      topicTags: ["bit-manipulation", "array", "dynamic-programming", "backtracking", "bitmask"],
+    },
+    "1948": {
+      topicTags: ["trie", "array", "hash-table", "string", "hash-function"],
+    },
+    "1949": { topicTags: ["database"] },
+    "1950": { topicTags: ["stack", "array", "monotonic-stack"] },
+    "1951": { topicTags: ["database"] },
+    "1952": { topicTags: ["math"] },
+    "1953": { topicTags: ["greedy", "array"] },
+    "1954": { topicTags: ["math", "binary-search"] },
+    "1955": { topicTags: ["array", "dynamic-programming"] },
+    "1956": {
+      topicTags: ["geometry", "array", "math", "binary-search", "enumeration"],
+    },
+    "1957": { topicTags: ["string"] },
+    "1958": { topicTags: ["array", "enumeration", "matrix"] },
+    "1959": { topicTags: ["array", "dynamic-programming"] },
+    "1960": { topicTags: ["string", "hash-function", "rolling-hash"] },
+    "1961": { topicTags: ["array", "string"] },
+    "1962": { topicTags: ["array", "heap-priority-queue"] },
+    "1963": { topicTags: ["stack", "greedy", "two-pointers", "string"] },
+    "1964": { topicTags: ["binary-indexed-tree", "array", "binary-search"] },
+    "1965": { topicTags: ["database"] },
+    "1966": { topicTags: ["array", "binary-search"] },
+    "1967": { topicTags: ["string"] },
+    "1968": { topicTags: ["greedy", "array", "sorting"] },
+    "1969": { topicTags: ["greedy", "recursion", "math"] },
+    "1970": {
+      topicTags: ["depth-first-search", "breadth-first-search", "union-find", "array", "binary-search", "matrix"],
+    },
+    "1971": {
+      topicTags: ["depth-first-search", "breadth-first-search", "union-find", "graph"],
+    },
+    "1972": { topicTags: ["database"] },
+    "1973": { topicTags: [] },
+    "1974": { topicTags: ["greedy", "string"] },
+    "1975": { topicTags: ["greedy", "array", "matrix"] },
+    "1976": {
+      topicTags: ["graph", "topological-sort", "dynamic-programming", "shortest-path"],
+    },
+    "1977": { topicTags: ["string", "dynamic-programming", "suffix-array"] },
+    "1978": { topicTags: [] },
+    "1979": { topicTags: ["array", "math", "number-theory"] },
+    "1980": { topicTags: ["array", "string", "backtracking"] },
+    "1981": { topicTags: ["array", "dynamic-programming", "matrix"] },
+    "1982": { topicTags: ["array", "divide-and-conquer"] },
+    "1983": { topicTags: ["array", "hash-table", "prefix-sum"] },
+    "1984": { topicTags: ["array", "sorting", "sliding-window"] },
+    "1985": {
+      topicTags: ["array", "string", "divide-and-conquer", "quickselect", "sorting", "heap-priority-queue"],
+    },
+    "1986": {
+      topicTags: ["bit-manipulation", "array", "dynamic-programming", "backtracking", "bitmask"],
+    },
+    "1987": { topicTags: ["string", "dynamic-programming"] },
+    "1988": { topicTags: [] },
+    "1989": { topicTags: [] },
+    "1990": { topicTags: [] },
+    "1991": { topicTags: ["array", "prefix-sum"] },
+    "1992": {
+      topicTags: ["depth-first-search", "breadth-first-search", "array", "matrix"],
+    },
+    "1993": {
+      topicTags: ["tree", "depth-first-search", "breadth-first-search", "design", "hash-table"],
+    },
+    "1994": {
+      topicTags: ["bit-manipulation", "array", "math", "dynamic-programming", "bitmask"],
+    },
+    "1995": { topicTags: ["array", "enumeration"] },
+    "1996": {
+      topicTags: ["stack", "greedy", "array", "sorting", "monotonic-stack"],
+    },
+    "1997": { topicTags: ["array", "dynamic-programming"] },
+    "1998": { topicTags: ["union-find", "array", "math", "sorting"] },
+    "1999": { topicTags: [] },
+    "2000": { topicTags: ["two-pointers", "string"] },
+    "2001": {
+      topicTags: ["array", "hash-table", "math", "counting", "number-theory"],
+    },
+    "2002": {
+      topicTags: ["bit-manipulation", "string", "dynamic-programming", "backtracking", "bitmask"],
+    },
+    "2003": {
+      topicTags: ["tree", "depth-first-search", "union-find", "dynamic-programming"],
+    },
+    "2004": { topicTags: [] },
+    "2005": { topicTags: [] },
+    "2006": { topicTags: ["array", "hash-table", "counting"] },
+    "2007": { topicTags: ["greedy", "array", "hash-table", "sorting"] },
+    "2008": {
+      topicTags: ["array", "binary-search", "dynamic-programming", "sorting"],
+    },
+    "2009": { topicTags: ["array", "binary-search"] },
+    "2010": { topicTags: [] },
+    "2011": { topicTags: ["array", "string", "simulation"] },
+    "2012": { topicTags: ["array"] },
+    "2013": { topicTags: ["design", "array", "hash-table", "counting"] },
+    "2014": {
+      topicTags: ["greedy", "string", "backtracking", "counting", "enumeration"],
+    },
+    "2015": {
+      topicTags: ["greedy", "array", "sorting", "heap-priority-queue"],
+    },
+    "2016": { topicTags: ["array"] },
+    "2017": { topicTags: ["array", "matrix", "prefix-sum"] },
+    "2018": { topicTags: ["array", "enumeration", "matrix"] },
+    "2019": {
+      topicTags: ["stack", "memoization", "array", "math", "string", "dynamic-programming"],
+    },
+    "2020": { topicTags: ["database"] },
+    "2021": { topicTags: ["array", "ordered-set", "prefix-sum"] },
+    "2022": { topicTags: ["array", "matrix", "simulation"] },
+    "2023": { topicTags: ["array", "string"] },
+    "2024": {
+      topicTags: ["string", "binary-search", "prefix-sum", "sliding-window"],
+    },
+    "2025": {
+      topicTags: ["array", "hash-table", "counting", "enumeration", "prefix-sum"],
+    },
+    "2026": { topicTags: ["database"] },
+    "2027": { topicTags: ["greedy", "string"] },
+    "2028": { topicTags: ["array", "math", "simulation"] },
+    "2029": {
+      topicTags: ["greedy", "array", "math", "counting", "game-theory"],
+    },
+    "2030": { topicTags: ["stack", "greedy", "string", "monotonic-stack"] },
+    "2031": {
+      topicTags: [
+        "binary-indexed-tree",
+        "segment-tree",
+        "array",
+        "binary-search",
+        "divide-and-conquer",
+        "ordered-set",
+        "merge-sort",
+      ],
+    },
+    "2032": { topicTags: ["array", "hash-table"] },
+    "2033": { topicTags: ["array", "math", "matrix", "sorting"] },
+    "2034": {
+      topicTags: ["design", "hash-table", "data-stream", "ordered-set", "heap-priority-queue"],
+    },
+    "2035": {
+      topicTags: [
+        "bit-manipulation",
+        "array",
+        "two-pointers",
+        "binary-search",
+        "dynamic-programming",
+        "bitmask",
+        "ordered-set",
+      ],
+    },
+    "2036": { topicTags: ["array", "dynamic-programming"] },
+    "2037": { topicTags: ["array", "sorting"] },
+    "2038": { topicTags: ["greedy", "math", "string", "game-theory"] },
+    "2039": { topicTags: ["breadth-first-search", "graph", "array"] },
+    "2040": { topicTags: ["array", "binary-search"] },
+    "2041": { topicTags: ["database"] },
+    "2042": { topicTags: ["string"] },
+    "2043": { topicTags: ["design", "array", "hash-table", "simulation"] },
+    "2044": { topicTags: ["bit-manipulation", "array", "backtracking"] },
+    "2045": { topicTags: ["breadth-first-search", "graph", "shortest-path"] },
+    "2046": { topicTags: ["linked-list", "two-pointers", "sorting"] },
+    "2047": { topicTags: ["string"] },
+    "2048": { topicTags: ["math", "backtracking", "enumeration"] },
+    "2049": {
+      topicTags: ["tree", "depth-first-search", "array", "binary-tree"],
+    },
+    "2050": { topicTags: ["graph", "topological-sort", "dynamic-programming"] },
+    "2051": { topicTags: ["database"] },
+    "2052": { topicTags: ["array", "dynamic-programming"] },
+    "2053": { topicTags: ["array", "hash-table", "string", "counting"] },
+    "2054": {
+      topicTags: ["array", "binary-search", "dynamic-programming", "sorting", "heap-priority-queue"],
+    },
+    "2055": { topicTags: ["array", "string", "binary-search", "prefix-sum"] },
+    "2056": { topicTags: ["array", "string", "backtracking", "simulation"] },
+    "2057": { topicTags: ["array"] },
+    "2058": { topicTags: ["linked-list"] },
+    "2059": { topicTags: ["breadth-first-search", "array"] },
+    "2060": { topicTags: ["string", "dynamic-programming"] },
+    "2061": { topicTags: ["array", "matrix", "simulation"] },
+    "2062": { topicTags: ["hash-table", "string"] },
+    "2063": {
+      topicTags: ["math", "string", "dynamic-programming", "combinatorics"],
+    },
+    "2064": { topicTags: ["array", "binary-search"] },
+    "2065": { topicTags: ["graph", "array", "backtracking"] },
+    "2066": { topicTags: ["database"] },
+    "2067": { topicTags: ["string", "counting", "prefix-sum"] },
+    "2068": { topicTags: ["hash-table", "string", "counting"] },
+    "2069": { topicTags: ["design", "simulation"] },
+    "2070": { topicTags: ["array", "binary-search", "sorting"] },
+    "2071": {
+      topicTags: ["greedy", "queue", "array", "binary-search", "sorting", "monotonic-queue"],
+    },
+    "2072": { topicTags: ["database"] },
+    "2073": { topicTags: ["queue", "array", "simulation"] },
+    "2074": { topicTags: ["linked-list"] },
+    "2075": { topicTags: ["string", "simulation"] },
+    "2076": { topicTags: ["union-find", "graph"] },
+    "2077": { topicTags: ["graph"] },
+    "2078": { topicTags: ["greedy", "array"] },
+    "2079": { topicTags: ["array"] },
+    "2080": {
+      topicTags: ["design", "segment-tree", "array", "hash-table", "binary-search"],
+    },
+    "2081": { topicTags: ["math", "enumeration"] },
+    "2082": { topicTags: ["database"] },
+    "2083": {
+      topicTags: ["hash-table", "math", "string", "counting", "prefix-sum"],
+    },
+    "2084": { topicTags: ["database"] },
+    "2085": { topicTags: ["array", "hash-table", "string", "counting"] },
+    "2086": { topicTags: ["greedy", "string", "dynamic-programming"] },
+    "2087": { topicTags: ["greedy", "array", "matrix"] },
+    "2088": { topicTags: ["array", "dynamic-programming", "matrix"] },
+    "2089": { topicTags: ["array", "binary-search", "sorting"] },
+    "2090": { topicTags: ["array", "sliding-window"] },
+    "2091": { topicTags: ["greedy", "array"] },
+    "2092": {
+      topicTags: ["depth-first-search", "breadth-first-search", "union-find", "graph", "sorting"],
+    },
+    "2093": { topicTags: ["graph", "shortest-path"] },
+    "2094": { topicTags: ["array", "hash-table", "enumeration", "sorting"] },
+    "2095": { topicTags: ["linked-list", "two-pointers"] },
+    "2096": {
+      topicTags: ["tree", "depth-first-search", "string", "binary-tree"],
+    },
+    "2097": { topicTags: ["depth-first-search", "graph", "eulerian-circuit"] },
+    "2098": { topicTags: ["greedy", "array", "sorting"] },
+    "2099": {
+      topicTags: ["array", "hash-table", "sorting", "heap-priority-queue"],
+    },
+    "2100": { topicTags: ["array", "dynamic-programming", "prefix-sum"] },
+    "2101": {
+      topicTags: ["depth-first-search", "breadth-first-search", "graph", "geometry", "array", "math"],
+    },
+    "2102": {
+      topicTags: ["design", "data-stream", "ordered-set", "heap-priority-queue"],
+    },
+    "2103": { topicTags: ["hash-table", "string"] },
+    "2104": { topicTags: ["stack", "array", "monotonic-stack"] },
+    "2105": { topicTags: ["array", "two-pointers", "simulation"] },
+    "2106": {
+      topicTags: ["array", "binary-search", "prefix-sum", "sliding-window"],
+    },
+    "2107": { topicTags: ["array", "hash-table", "sliding-window"] },
+    "2108": { topicTags: ["array", "two-pointers", "string"] },
+    "2109": { topicTags: ["array", "string", "simulation"] },
+    "2110": { topicTags: ["array", "math", "dynamic-programming"] },
+    "2111": { topicTags: ["array", "binary-search"] },
+    "2112": { topicTags: ["database"] },
+    "2113": { topicTags: ["array"] },
+    "2114": { topicTags: ["array", "string"] },
+    "2115": {
+      topicTags: ["graph", "topological-sort", "array", "hash-table", "string"],
+    },
+    "2116": { topicTags: ["stack", "greedy", "string"] },
+    "2117": { topicTags: ["math"] },
+    "2118": { topicTags: ["database"] },
+    "2119": { topicTags: ["math"] },
+    "2120": { topicTags: ["string", "simulation"] },
+    "2121": { topicTags: ["array", "hash-table", "prefix-sum"] },
+    "2122": { topicTags: ["array", "hash-table", "enumeration", "sorting"] },
+    "2123": { topicTags: ["graph", "array", "matrix"] },
+    "2124": { topicTags: ["string"] },
+    "2125": { topicTags: ["array", "math", "string", "matrix"] },
+    "2126": { topicTags: ["greedy", "array", "sorting"] },
+    "2127": { topicTags: ["depth-first-search", "graph", "topological-sort"] },
+    "2128": { topicTags: ["bit-manipulation", "array", "math", "matrix"] },
+    "2129": { topicTags: ["string"] },
+    "2130": { topicTags: ["stack", "linked-list", "two-pointers"] },
+    "2131": {
+      topicTags: ["greedy", "array", "hash-table", "string", "counting"],
+    },
+    "2132": { topicTags: ["greedy", "array", "matrix", "prefix-sum"] },
+    "2133": { topicTags: ["array", "hash-table", "matrix"] },
+    "2134": { topicTags: ["array", "sliding-window"] },
+    "2135": {
+      topicTags: ["bit-manipulation", "array", "hash-table", "string", "sorting"],
+    },
+    "2136": { topicTags: ["greedy", "array", "sorting"] },
+    "2137": { topicTags: ["array", "binary-search"] },
+    "2138": { topicTags: ["string", "simulation"] },
+    "2139": { topicTags: ["greedy", "math"] },
+    "2140": { topicTags: ["array", "dynamic-programming"] },
+    "2141": { topicTags: ["greedy", "array", "binary-search", "sorting"] },
+    "2142": { topicTags: ["database"] },
+    "2143": { topicTags: ["array", "dynamic-programming"] },
+    "2144": { topicTags: ["greedy", "array", "sorting"] },
+    "2145": { topicTags: ["array", "prefix-sum"] },
+    "2146": {
+      topicTags: ["breadth-first-search", "array", "matrix", "sorting", "heap-priority-queue"],
+    },
+    "2147": { topicTags: ["math", "string", "dynamic-programming"] },
+    "2148": { topicTags: ["array", "sorting"] },
+    "2149": { topicTags: ["array", "two-pointers", "simulation"] },
+    "2150": { topicTags: ["array", "hash-table", "counting"] },
+    "2151": {
+      topicTags: ["bit-manipulation", "array", "backtracking", "enumeration"],
+    },
+    "2152": {
+      topicTags: [
+        "bit-manipulation",
+        "geometry",
+        "array",
+        "hash-table",
+        "math",
+        "dynamic-programming",
+        "backtracking",
+        "bitmask",
+      ],
+    },
+    "2153": { topicTags: ["database"] },
+    "2154": { topicTags: ["array", "hash-table", "sorting", "simulation"] },
+    "2155": { topicTags: ["array"] },
+    "2156": {
+      topicTags: ["string", "sliding-window", "hash-function", "rolling-hash"],
+    },
+    "2157": { topicTags: ["bit-manipulation", "union-find", "string"] },
+    "2158": { topicTags: ["segment-tree", "array", "ordered-set"] },
+    "2159": { topicTags: ["database"] },
+    "2160": { topicTags: ["greedy", "math", "sorting"] },
+    "2161": { topicTags: ["array", "two-pointers", "simulation"] },
+    "2162": { topicTags: ["math", "enumeration"] },
+    "2163": {
+      topicTags: ["array", "dynamic-programming", "heap-priority-queue"],
+    },
+    "2164": { topicTags: ["array", "sorting"] },
+    "2165": { topicTags: ["math", "sorting"] },
+    "2166": { topicTags: ["design", "array", "hash-table"] },
+    "2167": { topicTags: ["string", "dynamic-programming"] },
+    "2168": {
+      topicTags: ["hash-table", "string", "counting", "hash-function", "rolling-hash"],
+    },
+    "2169": { topicTags: ["math", "simulation"] },
+    "2170": { topicTags: ["greedy", "array", "hash-table", "counting"] },
+    "2171": { topicTags: ["array", "prefix-sum", "sorting"] },
+    "2172": {
+      topicTags: ["bit-manipulation", "array", "dynamic-programming", "bitmask"],
+    },
+    "2173": { topicTags: ["database"] },
+    "2174": {
+      topicTags: ["bit-manipulation", "breadth-first-search", "array", "matrix"],
+    },
+    "2175": { topicTags: ["database"] },
+    "2176": { topicTags: ["array"] },
+    "2177": { topicTags: ["math", "simulation"] },
+    "2178": { topicTags: ["greedy", "math", "backtracking"] },
+    "2179": {
+      topicTags: [
+        "binary-indexed-tree",
+        "segment-tree",
+        "array",
+        "binary-search",
+        "divide-and-conquer",
+        "ordered-set",
+        "merge-sort",
+      ],
+    },
+    "2180": { topicTags: ["math", "simulation"] },
+    "2181": { topicTags: ["linked-list", "simulation"] },
+    "2182": {
+      topicTags: ["greedy", "string", "counting", "heap-priority-queue"],
+    },
+    "2183": { topicTags: ["array", "math", "number-theory"] },
+    "2184": {
+      topicTags: ["bit-manipulation", "array", "dynamic-programming", "bitmask"],
+    },
+    "2185": { topicTags: ["array", "string"] },
+    "2186": { topicTags: ["hash-table", "string", "counting"] },
+    "2187": { topicTags: ["array", "binary-search"] },
+    "2188": { topicTags: ["array", "dynamic-programming"] },
+    "2189": { topicTags: ["math", "dynamic-programming"] },
+    "2190": { topicTags: ["array", "hash-table", "counting"] },
+    "2191": { topicTags: ["array", "sorting"] },
+    "2192": {
+      topicTags: ["depth-first-search", "breadth-first-search", "graph", "topological-sort"],
+    },
+    "2193": {
+      topicTags: ["greedy", "binary-indexed-tree", "two-pointers", "string"],
+    },
+    "2194": { topicTags: ["string"] },
+    "2195": { topicTags: ["greedy", "array", "math", "sorting"] },
+    "2196": {
+      topicTags: ["tree", "depth-first-search", "breadth-first-search", "array", "hash-table", "binary-tree"],
+    },
+    "2197": { topicTags: ["stack", "array", "math", "number-theory"] },
+    "2198": { topicTags: ["math"] },
+    "2199": { topicTags: ["database"] },
+    "2200": { topicTags: ["array"] },
+    "2201": { topicTags: ["array", "hash-table", "simulation"] },
+    "2202": { topicTags: ["greedy", "array"] },
+    "2203": { topicTags: ["graph", "shortest-path"] },
+    "2204": {
+      topicTags: ["depth-first-search", "breadth-first-search", "union-find", "graph"],
+    },
+    "2205": { topicTags: ["database"] },
+    "2206": {
+      topicTags: ["bit-manipulation", "array", "hash-table", "counting"],
+    },
+    "2207": { topicTags: ["greedy", "string", "prefix-sum"] },
+    "2208": { topicTags: ["greedy", "array", "heap-priority-queue"] },
+    "2209": { topicTags: ["string", "dynamic-programming", "prefix-sum"] },
+    "2210": { topicTags: ["array"] },
+    "2211": { topicTags: ["stack", "string"] },
+    "2212": {
+      topicTags: ["bit-manipulation", "recursion", "array", "enumeration"],
+    },
+    "2213": { topicTags: ["segment-tree", "array", "string", "ordered-set"] },
+    "2214": { topicTags: ["greedy", "array", "prefix-sum"] },
+    "2215": { topicTags: ["array", "hash-table"] },
+    "2216": { topicTags: ["stack", "greedy", "array"] },
+    "2217": { topicTags: ["array", "math"] },
+    "2218": { topicTags: ["array", "dynamic-programming", "prefix-sum"] },
+    "2219": { topicTags: ["array", "prefix-sum"] },
+    "2220": { topicTags: ["bit-manipulation"] },
+    "2221": { topicTags: ["array", "math", "combinatorics", "simulation"] },
+    "2222": { topicTags: ["string", "dynamic-programming", "prefix-sum"] },
+    "2223": {
+      topicTags: ["string", "binary-search", "string-matching", "suffix-array", "hash-function", "rolling-hash"],
+    },
+    "2224": { topicTags: ["greedy", "string"] },
+    "2225": { topicTags: ["array", "hash-table", "counting", "sorting"] },
+    "2226": { topicTags: ["array", "binary-search"] },
+    "2227": { topicTags: ["design", "trie", "array", "hash-table", "string"] },
+    "2228": { topicTags: ["database"] },
+    "2229": { topicTags: ["array"] },
+    "2230": { topicTags: ["database"] },
+    "2231": { topicTags: ["sorting", "heap-priority-queue"] },
+    "2232": { topicTags: ["string", "enumeration"] },
+    "2233": { topicTags: ["greedy", "array", "heap-priority-queue"] },
+    "2234": {
+      topicTags: ["greedy", "array", "two-pointers", "binary-search", "sorting"],
+    },
+    "2235": { topicTags: ["math"] },
+    "2236": { topicTags: ["tree", "binary-tree"] },
+    "2237": { topicTags: ["array", "prefix-sum"] },
+    "2238": { topicTags: ["database"] },
+    "2239": { topicTags: ["array"] },
+    "2240": { topicTags: ["math", "enumeration"] },
+    "2241": { topicTags: ["greedy", "design", "array"] },
+    "2242": { topicTags: ["graph", "array", "enumeration", "sorting"] },
+    "2243": { topicTags: ["string", "simulation"] },
+    "2244": { topicTags: ["greedy", "array", "hash-table", "counting"] },
+    "2245": { topicTags: ["array", "matrix", "prefix-sum"] },
+    "2246": {
+      topicTags: ["tree", "depth-first-search", "graph", "topological-sort", "array", "string"],
+    },
+    "2247": {
+      topicTags: ["bit-manipulation", "graph", "dynamic-programming", "bitmask"],
+    },
+    "2248": { topicTags: ["array", "hash-table", "counting"] },
+    "2249": {
+      topicTags: ["geometry", "array", "hash-table", "math", "enumeration"],
+    },
+    "2250": {
+      topicTags: ["binary-indexed-tree", "array", "binary-search", "sorting"],
+    },
+    "2251": {
+      topicTags: ["array", "hash-table", "binary-search", "ordered-set", "prefix-sum", "sorting"],
+    },
+    "2252": { topicTags: ["database"] },
+    "2253": { topicTags: ["database"] },
+    "2254": { topicTags: ["stack", "design", "hash-table", "ordered-set"] },
+    "2255": { topicTags: ["array", "string"] },
+    "2256": { topicTags: ["array", "prefix-sum"] },
+    "2257": { topicTags: ["array", "matrix", "simulation"] },
+    "2258": {
+      topicTags: ["breadth-first-search", "array", "binary-search", "matrix"],
+    },
+    "2259": { topicTags: ["greedy", "string", "enumeration"] },
+    "2260": { topicTags: ["array", "hash-table", "sliding-window"] },
+    "2261": {
+      topicTags: ["trie", "array", "hash-table", "enumeration", "hash-function", "rolling-hash"],
+    },
+    "2262": { topicTags: ["hash-table", "string", "dynamic-programming"] },
+    "2263": { topicTags: ["greedy", "dynamic-programming"] },
+    "2264": { topicTags: ["string"] },
+    "2265": { topicTags: ["tree", "depth-first-search", "binary-tree"] },
+    "2266": {
+      topicTags: ["hash-table", "math", "string", "dynamic-programming"],
+    },
+    "2267": { topicTags: ["array", "dynamic-programming", "matrix"] },
+    "2268": { topicTags: ["greedy", "array", "string", "counting", "sorting"] },
+    "2269": { topicTags: ["math", "string", "sliding-window"] },
+    "2270": { topicTags: [] },
+    "2271": {
+      topicTags: ["greedy", "array", "binary-search", "prefix-sum", "sorting"],
+    },
+    "2272": { topicTags: ["array", "dynamic-programming"] },
+    "2273": { topicTags: ["array", "hash-table", "string", "sorting"] },
+    "2274": { topicTags: ["array", "sorting"] },
+    "2275": {
+      topicTags: ["bit-manipulation", "array", "hash-table", "counting"],
+    },
+    "2276": { topicTags: ["design", "segment-tree", "ordered-set"] },
+    "2277": {
+      topicTags: ["tree", "depth-first-search", "breadth-first-search", "array"],
+    },
+    "2278": { topicTags: ["string"] },
+    "2279": { topicTags: ["greedy", "array", "sorting"] },
+    "2280": {
+      topicTags: ["geometry", "array", "math", "number-theory", "sorting"],
+    },
+    "2281": { topicTags: ["stack", "array", "prefix-sum", "monotonic-stack"] },
+    "2282": { topicTags: ["stack", "array", "matrix", "monotonic-stack"] },
+    "2283": { topicTags: ["hash-table", "string", "counting"] },
+    "2284": { topicTags: ["array", "hash-table", "string", "counting"] },
+    "2285": {
+      topicTags: ["greedy", "graph", "sorting", "heap-priority-queue"],
+    },
+    "2286": {
+      topicTags: ["design", "binary-indexed-tree", "segment-tree", "binary-search"],
+    },
+    "2287": { topicTags: ["hash-table", "string", "counting"] },
+    "2288": { topicTags: ["string"] },
+    "2289": { topicTags: ["stack", "array", "linked-list", "monotonic-stack"] },
+    "2290": {
+      topicTags: ["breadth-first-search", "graph", "array", "matrix", "shortest-path", "heap-priority-queue"],
+    },
+    "2291": { topicTags: ["array", "dynamic-programming"] },
+    "2292": { topicTags: ["database"] },
+    "2293": { topicTags: ["array", "simulation"] },
+    "2294": { topicTags: ["greedy", "array", "sorting"] },
+    "2295": { topicTags: ["array", "hash-table", "simulation"] },
+    "2296": {
+      topicTags: ["stack", "design", "linked-list", "string", "doubly-linked-list", "simulation"],
+    },
+    "2297": {
+      topicTags: ["stack", "graph", "array", "dynamic-programming", "shortest-path", "monotonic-stack"],
+    },
+    "2298": { topicTags: ["database"] },
+    "2299": { topicTags: ["string"] },
+    "2300": {
+      topicTags: ["array", "two-pointers", "binary-search", "sorting"],
+    },
+    "2301": { topicTags: ["array", "hash-table", "string", "string-matching"] },
+    "2302": {
+      topicTags: ["array", "binary-search", "prefix-sum", "sliding-window"],
+    },
+    "2303": { topicTags: ["array", "simulation"] },
+    "2304": { topicTags: ["array", "dynamic-programming", "matrix"] },
+    "2305": {
+      topicTags: ["bit-manipulation", "array", "dynamic-programming", "backtracking", "bitmask"],
+    },
+    "2306": {
+      topicTags: ["bit-manipulation", "array", "hash-table", "string", "enumeration"],
+    },
+    "2307": {
+      topicTags: ["depth-first-search", "union-find", "graph", "array"],
+    },
+    "2308": { topicTags: ["database"] },
+    "2309": { topicTags: ["hash-table", "string", "enumeration"] },
+    "2310": {
+      topicTags: ["greedy", "math", "dynamic-programming", "enumeration"],
+    },
+    "2311": {
+      topicTags: ["greedy", "memoization", "string", "dynamic-programming"],
+    },
+    "2312": { topicTags: ["memoization", "array", "dynamic-programming"] },
+    "2313": {
+      topicTags: ["tree", "depth-first-search", "dynamic-programming", "binary-tree"],
+    },
+    "2314": { topicTags: ["database"] },
+    "2315": { topicTags: ["string"] },
+    "2316": {
+      topicTags: ["depth-first-search", "breadth-first-search", "union-find", "graph"],
+    },
+    "2317": { topicTags: ["bit-manipulation", "array", "math"] },
+    "2318": { topicTags: ["memoization", "dynamic-programming"] },
+    "2319": { topicTags: ["array", "matrix"] },
+    "2320": { topicTags: ["dynamic-programming"] },
+    "2321": { topicTags: ["array", "dynamic-programming"] },
+    "2322": {
+      topicTags: ["bit-manipulation", "tree", "depth-first-search", "array"],
+    },
+    "2323": { topicTags: ["greedy", "array", "sorting"] },
+    "2324": { topicTags: ["database"] },
+    "2325": { topicTags: ["hash-table", "string"] },
+    "2326": { topicTags: ["array", "linked-list", "matrix", "simulation"] },
+    "2327": { topicTags: ["queue", "dynamic-programming", "simulation"] },
+    "2328": {
+      topicTags: [
+        "depth-first-search",
+        "breadth-first-search",
+        "graph",
+        "topological-sort",
+        "memoization",
+        "array",
+        "dynamic-programming",
+        "matrix",
+      ],
+    },
+    "2329": { topicTags: ["database"] },
+    "2330": { topicTags: ["two-pointers", "string"] },
+    "2331": { topicTags: ["tree", "depth-first-search", "binary-search"] },
+    "2332": {
+      topicTags: ["array", "two-pointers", "binary-search", "sorting"],
+    },
+    "2333": { topicTags: ["array", "math", "sorting", "heap-priority-queue"] },
+    "2334": { topicTags: ["stack", "union-find", "array", "monotonic-stack"] },
+    "2335": { topicTags: ["greedy", "array", "heap-priority-queue"] },
+    "2336": { topicTags: ["design", "hash-table", "heap-priority-queue"] },
+    "2337": { topicTags: ["two-pointers", "string"] },
+    "2338": {
+      topicTags: ["math", "dynamic-programming", "combinatorics", "number-theory"],
+    },
+    "2339": { topicTags: ["database"] },
+    "2340": { topicTags: ["greedy", "array"] },
+    "2341": { topicTags: ["array", "hash-table", "counting"] },
+    "2342": {
+      topicTags: ["array", "hash-table", "sorting", "heap-priority-queue"],
+    },
+    "2343": {
+      topicTags: [
+        "array",
+        "string",
+        "divide-and-conquer",
+        "quickselect",
+        "radix-sort",
+        "sorting",
+        "heap-priority-queue",
+      ],
+    },
+    "2344": {
+      topicTags: ["array", "math", "number-theory", "sorting", "heap-priority-queue"],
+    },
+    "2345": { topicTags: ["stack", "array", "sorting", "monotonic-stack"] },
+    "2346": { topicTags: ["database"] },
+    "2347": { topicTags: ["array", "hash-table", "counting"] },
+    "2348": { topicTags: ["array", "math"] },
+    "2349": {
+      topicTags: ["design", "hash-table", "ordered-set", "heap-priority-queue"],
+    },
+    "2350": { topicTags: ["greedy", "array", "hash-table"] },
+    "2351": { topicTags: ["hash-table", "string", "counting"] },
+    "2352": { topicTags: ["array", "hash-table", "matrix", "simulation"] },
+    "2353": {
+      topicTags: ["design", "hash-table", "ordered-set", "heap-priority-queue"],
+    },
+    "2354": {
+      topicTags: ["bit-manipulation", "array", "hash-table", "binary-search"],
+    },
+    "2355": {
+      topicTags: ["stack", "array", "dynamic-programming", "monotonic-stack"],
+    },
+    "2356": { topicTags: ["database"] },
+    "2357": {
+      topicTags: ["array", "hash-table", "sorting", "simulation", "heap-priority-queue"],
+    },
+    "2358": { topicTags: ["greedy", "array", "math", "binary-search"] },
+    "2359": { topicTags: ["depth-first-search", "graph"] },
+    "2360": { topicTags: ["depth-first-search", "graph", "topological-sort"] },
+    "2361": { topicTags: ["array", "dynamic-programming"] },
+    "2362": { topicTags: ["database"] },
+    "2363": { topicTags: ["array", "hash-table", "ordered-set", "sorting"] },
+    "2364": { topicTags: ["array", "hash-table"] },
+    "2365": { topicTags: ["array", "hash-table", "simulation"] },
+    "2366": { topicTags: ["greedy", "array", "math"] },
+    "2367": {
+      topicTags: ["array", "hash-table", "two-pointers", "enumeration"],
+    },
+    "2368": {
+      topicTags: ["tree", "depth-first-search", "breadth-first-search", "graph", "array", "hash-table"],
+    },
+    "2369": { topicTags: ["array", "dynamic-programming"] },
+    "2370": { topicTags: ["hash-table", "string", "dynamic-programming"] },
+    "2371": {
+      topicTags: ["greedy", "union-find", "graph", "topological-sort", "array", "matrix", "sorting"],
+    },
+    "2372": { topicTags: ["database"] },
+    "2373": { topicTags: ["array", "matrix"] },
+    "2374": { topicTags: ["graph", "hash-table"] },
+    "2375": { topicTags: ["stack", "greedy", "string", "backtracking"] },
+    "2376": { topicTags: ["math", "dynamic-programming"] },
+    "2377": { topicTags: ["database"] },
+    "2378": {
+      topicTags: ["tree", "depth-first-search", "dynamic-programming"],
+    },
+    "2379": { topicTags: ["string", "sliding-window"] },
+    "2380": { topicTags: ["string", "dynamic-programming", "simulation"] },
+    "2381": { topicTags: ["array", "string", "prefix-sum"] },
+    "2382": { topicTags: ["union-find", "array", "ordered-set", "prefix-sum"] },
+    "2383": { topicTags: ["greedy", "array"] },
+    "2384": { topicTags: ["greedy", "hash-table", "string"] },
+    "2385": {
+      topicTags: ["tree", "depth-first-search", "breadth-first-search", "binary-tree"],
+    },
+    "2386": { topicTags: ["array", "sorting", "heap-priority-queue"] },
+    "2387": { topicTags: ["array", "binary-search", "matrix"] },
+    "2388": { topicTags: ["database"] },
+    "2389": {
+      topicTags: ["greedy", "array", "binary-search", "prefix-sum", "sorting"],
+    },
+    "2390": { topicTags: ["stack", "string", "simulation"] },
+    "2391": { topicTags: ["array", "string", "prefix-sum"] },
+    "2392": { topicTags: ["graph", "topological-sort", "array", "matrix"] },
+    "2393": { topicTags: ["array", "math", "dynamic-programming"] },
+    "2394": { topicTags: ["database"] },
+    "2395": { topicTags: ["array", "hash-table"] },
+    "2396": { topicTags: ["brainteaser", "math", "two-pointers"] },
+    "2397": {
+      topicTags: ["bit-manipulation", "array", "backtracking", "enumeration", "matrix"],
+    },
+    "2398": {
+      topicTags: ["queue", "array", "binary-search", "prefix-sum", "sliding-window", "heap-priority-queue"],
+    },
+    "2399": { topicTags: ["array", "hash-table", "string"] },
+    "2400": { topicTags: ["math", "dynamic-programming", "combinatorics"] },
+    "2401": { topicTags: ["bit-manipulation", "array", "sliding-window"] },
+    "2402": { topicTags: ["array", "sorting", "heap-priority-queue"] },
+    "2403": {
+      topicTags: ["bit-manipulation", "array", "dynamic-programming", "bitmask"],
+    },
+    "2404": { topicTags: ["array", "hash-table", "counting"] },
+    "2405": { topicTags: ["greedy", "hash-table", "string"] },
+    "2406": {
+      topicTags: ["greedy", "array", "two-pointers", "prefix-sum", "sorting", "heap-priority-queue"],
+    },
+    "2407": {
+      topicTags: [
+        "binary-indexed-tree",
+        "segment-tree",
+        "queue",
+        "array",
+        "divide-and-conquer",
+        "dynamic-programming",
+        "monotonic-queue",
+      ],
+    },
+    "2408": { topicTags: ["design", "array", "hash-table", "string"] },
+    "2409": { topicTags: ["math", "string"] },
+    "2410": { topicTags: ["greedy", "array", "two-pointers", "sorting"] },
+    "2411": {
+      topicTags: ["bit-manipulation", "array", "binary-search", "sliding-window"],
+    },
+    "2412": { topicTags: ["greedy", "array", "sorting"] },
+    "2413": { topicTags: ["math", "number-theory"] },
+    "2414": { topicTags: ["string"] },
+    "2415": {
+      topicTags: ["tree", "depth-first-search", "breadth-first-search", "binary-tree"],
+    },
+    "2416": { topicTags: ["trie", "array", "string", "counting"] },
+    "2417": { topicTags: ["math", "enumeration"] },
+    "2418": { topicTags: ["array", "hash-table", "string", "sorting"] },
+    "2419": { topicTags: ["bit-manipulation", "brainteaser", "array"] },
+    "2420": { topicTags: ["array", "dynamic-programming", "prefix-sum"] },
+    "2421": { topicTags: ["tree", "union-find", "graph", "array"] },
+    "LCP 01": { topicTags: ["array"] },
+    "LCP 02": { topicTags: ["array", "math", "number-theory", "simulation"] },
+    "LCP 03": { topicTags: ["array", "hash-table", "simulation"] },
+    "LCP 04": {
+      topicTags: ["bit-manipulation", "graph", "array", "dynamic-programming", "bitmask"],
+    },
+    "LCP 05": { topicTags: ["binary-indexed-tree", "segment-tree", "array"] },
+    "LCP 06": { topicTags: ["array", "math"] },
+    "LCP 07": {
+      topicTags: ["depth-first-search", "breadth-first-search", "graph", "dynamic-programming"],
+    },
+    "LCP 08": { topicTags: ["array", "binary-search", "sorting"] },
+    "LCP 09": {
+      topicTags: ["breadth-first-search", "segment-tree", "array", "dynamic-programming"],
+    },
+    "LCP 10": {
+      topicTags: ["tree", "depth-first-search", "dynamic-programming", "binary-tree"],
+    },
+    "LCP 11": {
+      topicTags: ["array", "hash-table", "math", "probability-and-statistics"],
+    },
+    "LCP 12": { topicTags: ["array", "binary-search"] },
+    "LCP 13": {
+      topicTags: ["bit-manipulation", "breadth-first-search", "array", "dynamic-programming", "bitmask", "matrix"],
+    },
+    "LCP 14": {
+      topicTags: ["array", "math", "dynamic-programming", "number-theory"],
+    },
+    "LCP 15": { topicTags: ["greedy", "geometry", "array", "math"] },
+    "LCP 16": { topicTags: ["graph", "geometry", "math"] },
+    "LCP 17": { topicTags: ["math", "string", "simulation"] },
+    "LCP 18": {
+      topicTags: ["array", "two-pointers", "binary-search", "sorting"],
+    },
+    "LCP 19": { topicTags: ["string", "dynamic-programming"] },
+    "LCP 20": { topicTags: ["memoization", "array", "dynamic-programming"] },
+    "LCP 21": {
+      topicTags: ["depth-first-search", "breadth-first-search", "graph", "topological-sort"],
+    },
+    "LCP 22": { topicTags: ["math"] },
+    "LCP 23": { topicTags: ["queue", "array", "simulation"] },
+    "LCP 24": { topicTags: ["array", "math", "heap-priority-queue"] },
+    "LCP 25": { topicTags: ["math", "dynamic-programming", "combinatorics"] },
+    "LCP 26": { topicTags: ["tree", "dynamic-programming", "binary-tree"] },
+    "LCP 27": { topicTags: ["design", "segment-tree", "math", "ordered-set"] },
+    "LCP 28": {
+      topicTags: ["array", "two-pointers", "binary-search", "sorting"],
+    },
+    "LCP 29": { topicTags: ["math"] },
+    "LCP 30": { topicTags: ["greedy", "array", "heap-priority-queue"] },
+    "LCP 31": {
+      topicTags: ["depth-first-search", "breadth-first-search", "array", "dynamic-programming", "matrix"],
+    },
+    "LCP 32": { topicTags: ["greedy", "array", "heap-priority-queue"] },
+    "LCP 33": { topicTags: ["greedy", "array", "heap-priority-queue"] },
+    "LCP 34": { topicTags: ["tree", "dynamic-programming", "binary-tree"] },
+    "LCP 35": { topicTags: ["graph", "shortest-path", "heap-priority-queue"] },
+    "LCP 36": { topicTags: ["array", "dynamic-programming", "sorting"] },
+    "LCP 37": {
+      topicTags: ["greedy", "geometry", "array", "math", "combinatorics", "sorting"],
+    },
+    "LCP 38": { topicTags: ["array", "dynamic-programming", "matrix"] },
+    "LCP 39": { topicTags: ["array", "hash-table", "counting", "matrix"] },
+    "LCP 40": { topicTags: ["greedy", "array", "sorting"] },
+    "LCP 41": { topicTags: ["breadth-first-search", "array", "matrix"] },
+    "LCP 42": {
+      topicTags: ["geometry", "array", "hash-table", "math", "binary-search", "sorting"],
+    },
+    "LCP 43": { topicTags: ["array", "string", "dynamic-programming"] },
+    "LCP 44": {
+      topicTags: ["tree", "depth-first-search", "breadth-first-search", "hash-table", "binary-tree"],
+    },
+    "LCP 45": {
+      topicTags: [
+        "depth-first-search",
+        "breadth-first-search",
+        "memoization",
+        "array",
+        "dynamic-programming",
+        "matrix",
+      ],
+    },
+    "LCP 46": { topicTags: ["graph", "array", "math"] },
+    "LCP 47": { topicTags: ["array", "dynamic-programming"] },
+    "LCP 48": { topicTags: ["array", "math", "enumeration", "game-theory"] },
+    "LCP 49": {
+      topicTags: ["bit-manipulation", "union-find", "array", "heap-priority-queue"],
+    },
+    "LCP 50": { topicTags: ["array", "simulation"] },
+    "LCP 51": {
+      topicTags: ["bit-manipulation", "array", "backtracking", "enumeration"],
+    },
+    "LCP 52": {
+      topicTags: ["tree", "segment-tree", "binary-search-tree", "array", "binary-search", "binary-tree", "ordered-set"],
+    },
+    "LCP 53": {
+      topicTags: ["bit-manipulation", "array", "dynamic-programming", "bitmask"],
+    },
+    "LCP 54": { topicTags: ["graph", "array", "biconnected-component"] },
+    "LCP 55": { topicTags: ["array"] },
+    "LCP 56": {
+      topicTags: ["breadth-first-search", "graph", "array", "matrix", "shortest-path", "heap-priority-queue"],
+    },
+    "LCP 57": {
+      topicTags: ["array", "dynamic-programming", "matrix", "sorting"],
+    },
+    "LCP 58": { topicTags: ["array", "backtracking", "matrix"] },
+    "LCP 59": { topicTags: ["array", "dynamic-programming"] },
+    "LCP 60": { topicTags: ["tree", "dynamic-programming", "binary-tree"] },
+    "LCP 61": { topicTags: [] },
+    "LCP 62": { topicTags: [] },
+    "LCP 63": { topicTags: [] },
+    "LCP 64": { topicTags: [] },
+    "LCP 65": { topicTags: [] },
+    "LCS 01": { topicTags: ["greedy", "math", "dynamic-programming"] },
+    "LCS 02": { topicTags: ["greedy", "array", "hash-table", "sorting"] },
+    "LCS 03": {
+      topicTags: ["depth-first-search", "breadth-first-search", "union-find", "array", "matrix"],
+    },
+    "剑指 Offer 03": { topicTags: ["array", "hash-table", "sorting"] },
+    "剑指 Offer 04": {
+      topicTags: ["array", "binary-search", "divide-and-conquer", "matrix"],
+    },
+    "剑指 Offer 05": { topicTags: ["string"] },
+    "剑指 Offer 06": {
+      topicTags: ["stack", "recursion", "linked-list", "two-pointers"],
+    },
+    "剑指 Offer 07": {
+      topicTags: ["tree", "array", "hash-table", "divide-and-conquer", "binary-tree"],
+    },
+    "剑指 Offer 09": { topicTags: ["stack", "design", "queue"] },
+    "剑指 Offer 10- I": {
+      topicTags: ["memoization", "math", "dynamic-programming"],
+    },
+    "剑指 Offer 10- II": {
+      topicTags: ["memoization", "math", "dynamic-programming"],
+    },
+    "剑指 Offer 11": { topicTags: ["array", "binary-search"] },
+    "剑指 Offer 12": { topicTags: ["array", "backtracking", "matrix"] },
+    "剑指 Offer 14- I": { topicTags: ["math", "dynamic-programming"] },
+    "剑指 Offer 14- II": { topicTags: ["math", "dynamic-programming"] },
+    "剑指 Offer 15": { topicTags: ["bit-manipulation"] },
+    "剑指 Offer 16": { topicTags: ["recursion", "math"] },
+    "剑指 Offer 17": { topicTags: ["array", "math"] },
+    "剑指 Offer 18": { topicTags: ["linked-list"] },
+    "剑指 Offer 19": {
+      topicTags: ["recursion", "string", "dynamic-programming"],
+    },
+    "剑指 Offer 20": { topicTags: ["string"] },
+    "剑指 Offer 21": { topicTags: ["array", "two-pointers", "sorting"] },
+    "剑指 Offer 22": { topicTags: ["linked-list", "two-pointers"] },
+    "剑指 Offer 24": { topicTags: ["recursion", "linked-list"] },
+    "剑指 Offer 25": { topicTags: ["recursion", "linked-list"] },
+    "剑指 Offer 26": {
+      topicTags: ["tree", "depth-first-search", "binary-tree"],
+    },
+    "剑指 Offer 27": {
+      topicTags: ["tree", "depth-first-search", "breadth-first-search", "binary-tree"],
+    },
+    "剑指 Offer 28": {
+      topicTags: ["tree", "depth-first-search", "breadth-first-search", "binary-tree"],
+    },
+    "剑指 Offer 29": { topicTags: ["array", "matrix", "simulation"] },
+    "剑指 Offer 30": { topicTags: ["stack", "design"] },
+    "剑指 Offer 31": { topicTags: ["stack", "array", "simulation"] },
+    "剑指 Offer 32 - I": {
+      topicTags: ["tree", "breadth-first-search", "binary-tree"],
+    },
+    "剑指 Offer 32 - II": {
+      topicTags: ["tree", "breadth-first-search", "binary-tree"],
+    },
+    "剑指 Offer 32 - III": {
+      topicTags: ["tree", "breadth-first-search", "binary-tree"],
+    },
+    "剑指 Offer 33": {
+      topicTags: ["stack", "tree", "binary-search-tree", "recursion", "binary-tree", "monotonic-stack"],
+    },
+    "剑指 Offer 34": {
+      topicTags: ["tree", "depth-first-search", "backtracking", "binary-tree"],
+    },
+    "剑指 Offer 35": { topicTags: ["hash-table", "linked-list"] },
+    "剑指 Offer 36": {
+      topicTags: [
+        "stack",
+        "tree",
+        "depth-first-search",
+        "binary-search-tree",
+        "linked-list",
+        "binary-tree",
+        "doubly-linked-list",
+      ],
+    },
+    "剑指 Offer 37": {
+      topicTags: ["tree", "depth-first-search", "breadth-first-search", "design", "string", "binary-tree"],
+    },
+    "剑指 Offer 38": { topicTags: ["string", "backtracking"] },
+    "剑指 Offer 39": {
+      topicTags: ["array", "hash-table", "divide-and-conquer", "counting", "sorting"],
+    },
+    "剑指 Offer 40": {
+      topicTags: ["array", "divide-and-conquer", "quickselect", "sorting", "heap-priority-queue"],
+    },
+    "剑指 Offer 41": {
+      topicTags: ["design", "two-pointers", "data-stream", "sorting", "heap-priority-queue"],
+    },
+    "剑指 Offer 42": {
+      topicTags: ["array", "divide-and-conquer", "dynamic-programming"],
+    },
+    "剑指 Offer 43": {
+      topicTags: ["recursion", "math", "dynamic-programming"],
+    },
+    "剑指 Offer 44": { topicTags: ["math", "binary-search"] },
+    "剑指 Offer 45": { topicTags: ["greedy", "string", "sorting"] },
+    "剑指 Offer 46": { topicTags: ["string", "dynamic-programming"] },
+    "剑指 Offer 47": { topicTags: ["array", "dynamic-programming", "matrix"] },
+    "剑指 Offer 48": { topicTags: ["hash-table", "string", "sliding-window"] },
+    "剑指 Offer 49": {
+      topicTags: ["hash-table", "math", "dynamic-programming", "heap-priority-queue"],
+    },
+    "剑指 Offer 50": {
+      topicTags: ["queue", "hash-table", "string", "counting"],
+    },
+    "剑指 Offer 51": {
+      topicTags: [
+        "binary-indexed-tree",
+        "segment-tree",
+        "array",
+        "binary-search",
+        "divide-and-conquer",
+        "ordered-set",
+        "merge-sort",
+      ],
+    },
+    "剑指 Offer 52": {
+      topicTags: ["hash-table", "linked-list", "two-pointers"],
+    },
+    "剑指 Offer 53 - I": { topicTags: ["array", "binary-search"] },
+    "剑指 Offer 53 - II": {
+      topicTags: ["bit-manipulation", "array", "hash-table", "math", "binary-search"],
+    },
+    "剑指 Offer 54": {
+      topicTags: ["tree", "depth-first-search", "binary-search-tree", "binary-tree"],
+    },
+    "剑指 Offer 55 - I": {
+      topicTags: ["tree", "depth-first-search", "breadth-first-search", "binary-tree"],
+    },
+    "剑指 Offer 55 - II": {
+      topicTags: ["tree", "depth-first-search", "binary-tree"],
+    },
+    "剑指 Offer 56 - I": { topicTags: ["bit-manipulation", "array"] },
+    "剑指 Offer 56 - II": { topicTags: ["bit-manipulation", "array"] },
+    "剑指 Offer 57": { topicTags: ["array", "two-pointers", "binary-search"] },
+    "剑指 Offer 57 - II": {
+      topicTags: ["math", "two-pointers", "enumeration"],
+    },
+    "剑指 Offer 58 - I": { topicTags: ["two-pointers", "string"] },
+    "剑指 Offer 58 - II": { topicTags: ["math", "two-pointers", "string"] },
+    "剑指 Offer 59 - I": {
+      topicTags: ["queue", "sliding-window", "monotonic-queue", "heap-priority-queue"],
+    },
+    "剑指 Offer 60": {
+      topicTags: ["math", "dynamic-programming", "probability-and-statistics"],
+    },
+    "剑指 Offer 61": { topicTags: ["array", "sorting"] },
+    "剑指 Offer 62": { topicTags: ["recursion", "math"] },
+    "剑指 Offer 63": { topicTags: ["array", "dynamic-programming"] },
+    "剑指 Offer 64": {
+      topicTags: ["bit-manipulation", "recursion", "brainteaser"],
+    },
+    "剑指 Offer 65": { topicTags: ["bit-manipulation", "math"] },
+    "剑指 Offer 66": { topicTags: ["array", "prefix-sum"] },
+    "剑指 Offer 67": { topicTags: ["string"] },
+    "剑指 Offer 68 - I": {
+      topicTags: ["tree", "depth-first-search", "binary-search-tree", "binary-tree"],
+    },
+    "剑指 Offer 68 - II": {
+      topicTags: ["tree", "depth-first-search", "binary-tree"],
+    },
+    "剑指 Offer II 001": { topicTags: ["bit-manipulation", "math"] },
+    "剑指 Offer II 002": {
+      topicTags: ["bit-manipulation", "math", "string", "simulation"],
+    },
+    "剑指 Offer II 003": {
+      topicTags: ["bit-manipulation", "dynamic-programming"],
+    },
+    "剑指 Offer II 004": { topicTags: ["bit-manipulation", "array"] },
+    "剑指 Offer II 005": { topicTags: ["bit-manipulation", "array", "string"] },
+    "剑指 Offer II 006": {
+      topicTags: ["array", "two-pointers", "binary-search"],
+    },
+    "剑指 Offer II 007": { topicTags: ["array", "two-pointers", "sorting"] },
+    "剑指 Offer II 008": {
+      topicTags: ["array", "binary-search", "prefix-sum", "sliding-window"],
+    },
+    "剑指 Offer II 009": { topicTags: ["array", "sliding-window"] },
+    "剑指 Offer II 010": { topicTags: ["array", "hash-table", "prefix-sum"] },
+    "剑指 Offer II 011": { topicTags: ["array", "hash-table", "prefix-sum"] },
+    "剑指 Offer II 012": { topicTags: ["array", "prefix-sum"] },
+    "剑指 Offer II 013": {
+      topicTags: ["design", "array", "matrix", "prefix-sum"],
+    },
+    "剑指 Offer II 014": {
+      topicTags: ["hash-table", "two-pointers", "string", "sliding-window"],
+    },
+    "剑指 Offer II 015": {
+      topicTags: ["hash-table", "string", "sliding-window"],
+    },
+    "剑指 Offer II 016": {
+      topicTags: ["hash-table", "string", "sliding-window"],
+    },
+    "剑指 Offer II 017": {
+      topicTags: ["hash-table", "string", "sliding-window"],
+    },
+    "剑指 Offer II 018": { topicTags: ["two-pointers", "string"] },
+    "剑指 Offer II 019": { topicTags: ["greedy", "two-pointers", "string"] },
+    "剑指 Offer II 020": { topicTags: ["string", "dynamic-programming"] },
+    "剑指 Offer II 021": { topicTags: ["linked-list", "two-pointers"] },
+    "剑指 Offer II 022": {
+      topicTags: ["hash-table", "linked-list", "two-pointers"],
+    },
+    "剑指 Offer II 023": {
+      topicTags: ["hash-table", "linked-list", "two-pointers"],
+    },
+    "剑指 Offer II 024": { topicTags: ["recursion", "linked-list"] },
+    "剑指 Offer II 025": { topicTags: ["stack", "linked-list", "math"] },
+    "剑指 Offer II 026": {
+      topicTags: ["stack", "recursion", "linked-list", "two-pointers"],
+    },
+    "剑指 Offer II 027": {
+      topicTags: ["stack", "recursion", "linked-list", "two-pointers"],
+    },
+    "剑指 Offer II 028": {
+      topicTags: ["depth-first-search", "linked-list", "doubly-linked-list"],
+    },
+    "剑指 Offer II 029": { topicTags: ["linked-list"] },
+    "剑指 Offer II 030": {
+      topicTags: ["design", "array", "hash-table", "math", "randomized"],
+    },
+    "剑指 Offer II 031": {
+      topicTags: ["design", "hash-table", "linked-list", "doubly-linked-list"],
+    },
+    "剑指 Offer II 032": { topicTags: ["hash-table", "string", "sorting"] },
+    "剑指 Offer II 033": {
+      topicTags: ["array", "hash-table", "string", "sorting"],
+    },
+    "剑指 Offer II 034": { topicTags: ["array", "hash-table", "string"] },
+    "剑指 Offer II 035": { topicTags: ["array", "math", "string", "sorting"] },
+    "剑指 Offer II 036": { topicTags: ["stack", "array", "math"] },
+    "剑指 Offer II 037": { topicTags: ["stack", "array"] },
+    "剑指 Offer II 038": { topicTags: ["stack", "array", "monotonic-stack"] },
+    "剑指 Offer II 039": { topicTags: ["stack", "array", "monotonic-stack"] },
+    "剑指 Offer II 040": {
+      topicTags: ["stack", "array", "dynamic-programming", "matrix", "monotonic-stack"],
+    },
+    "剑指 Offer II 041": {
+      topicTags: ["design", "queue", "array", "data-stream"],
+    },
+    "剑指 Offer II 042": { topicTags: ["design", "queue", "data-stream"] },
+    "剑指 Offer II 043": {
+      topicTags: ["tree", "breadth-first-search", "design", "binary-tree"],
+    },
+    "剑指 Offer II 044": {
+      topicTags: ["tree", "depth-first-search", "breadth-first-search", "binary-tree"],
+    },
+    "剑指 Offer II 045": {
+      topicTags: ["tree", "depth-first-search", "breadth-first-search", "binary-tree"],
+    },
+    "剑指 Offer II 046": {
+      topicTags: ["tree", "depth-first-search", "breadth-first-search", "binary-tree"],
+    },
+    "剑指 Offer II 047": {
+      topicTags: ["tree", "depth-first-search", "binary-tree"],
+    },
+    "剑指 Offer II 048": {
+      topicTags: ["tree", "depth-first-search", "breadth-first-search", "design", "string", "binary-tree"],
+    },
+    "剑指 Offer II 049": {
+      topicTags: ["tree", "depth-first-search", "binary-tree"],
+    },
+    "剑指 Offer II 050": {
+      topicTags: ["tree", "depth-first-search", "binary-tree"],
+    },
+    "剑指 Offer II 051": {
+      topicTags: ["tree", "depth-first-search", "dynamic-programming", "binary-tree"],
+    },
+    "剑指 Offer II 052": {
+      topicTags: ["stack", "tree", "depth-first-search", "binary-search-tree", "binary-tree"],
+    },
+    "剑指 Offer II 053": {
+      topicTags: ["tree", "depth-first-search", "binary-search-tree", "binary-tree"],
+    },
+    "剑指 Offer II 054": {
+      topicTags: ["tree", "depth-first-search", "binary-search-tree", "binary-tree"],
+    },
+    "剑指 Offer II 055": {
+      topicTags: ["stack", "tree", "design", "binary-search-tree", "binary-tree", "iterator"],
+    },
+    "剑指 Offer II 056": {
+      topicTags: [
+        "tree",
+        "depth-first-search",
+        "breadth-first-search",
+        "binary-search-tree",
+        "hash-table",
+        "two-pointers",
+        "binary-tree",
+      ],
+    },
+    "剑指 Offer II 057": {
+      topicTags: ["array", "bucket-sort", "ordered-set", "sorting", "sliding-window"],
+    },
+    "剑指 Offer II 058": {
+      topicTags: ["design", "segment-tree", "binary-search", "ordered-set"],
+    },
+    "剑指 Offer II 059": {
+      topicTags: ["tree", "design", "binary-search-tree", "binary-tree", "data-stream", "heap-priority-queue"],
+    },
+    "剑指 Offer II 060": {
+      topicTags: [
+        "array",
+        "hash-table",
+        "divide-and-conquer",
+        "bucket-sort",
+        "counting",
+        "quickselect",
+        "sorting",
+        "heap-priority-queue",
+      ],
+    },
+    "剑指 Offer II 061": { topicTags: ["array", "heap-priority-queue"] },
+    "剑指 Offer II 062": {
+      topicTags: ["design", "trie", "hash-table", "string"],
+    },
+    "剑指 Offer II 063": {
+      topicTags: ["trie", "array", "hash-table", "string"],
+    },
+    "剑指 Offer II 064": {
+      topicTags: ["design", "trie", "hash-table", "string"],
+    },
+    "剑指 Offer II 065": {
+      topicTags: ["trie", "array", "hash-table", "string"],
+    },
+    "剑指 Offer II 066": {
+      topicTags: ["design", "trie", "hash-table", "string"],
+    },
+    "剑指 Offer II 067": {
+      topicTags: ["bit-manipulation", "trie", "array", "hash-table"],
+    },
+    "剑指 Offer II 068": { topicTags: ["array", "binary-search"] },
+    "剑指 Offer II 069": { topicTags: ["array", "binary-search"] },
+    "剑指 Offer II 070": { topicTags: ["array", "binary-search"] },
+    "剑指 Offer II 071": {
+      topicTags: ["math", "binary-search", "prefix-sum", "randomized"],
+    },
+    "剑指 Offer II 072": { topicTags: ["math", "binary-search"] },
+    "剑指 Offer II 073": { topicTags: ["array", "binary-search"] },
+    "剑指 Offer II 074": { topicTags: ["array", "sorting"] },
+    "剑指 Offer II 075": {
+      topicTags: ["array", "hash-table", "counting-sort", "sorting"],
+    },
+    "剑指 Offer II 076": {
+      topicTags: ["array", "divide-and-conquer", "quickselect", "sorting", "heap-priority-queue"],
+    },
+    "剑指 Offer II 077": {
+      topicTags: ["linked-list", "two-pointers", "divide-and-conquer", "sorting", "merge-sort"],
+    },
+    "剑指 Offer II 078": {
+      topicTags: ["linked-list", "divide-and-conquer", "heap-priority-queue", "merge-sort"],
+    },
+    "剑指 Offer II 079": {
+      topicTags: ["bit-manipulation", "array", "backtracking"],
+    },
+    "剑指 Offer II 080": { topicTags: ["array", "backtracking"] },
+    "剑指 Offer II 081": { topicTags: ["array", "backtracking"] },
+    "剑指 Offer II 082": { topicTags: ["array", "backtracking"] },
+    "剑指 Offer II 083": { topicTags: ["array", "backtracking"] },
+    "剑指 Offer II 084": { topicTags: ["array", "backtracking"] },
+    "剑指 Offer II 085": {
+      topicTags: ["string", "dynamic-programming", "backtracking"],
+    },
+    "剑指 Offer II 086": {
+      topicTags: ["depth-first-search", "breadth-first-search", "graph", "hash-table"],
+    },
+    "剑指 Offer II 087": { topicTags: ["string", "backtracking"] },
+    "剑指 Offer II 088": { topicTags: ["array", "dynamic-programming"] },
+    "剑指 Offer II 089": { topicTags: ["array", "dynamic-programming"] },
+    "剑指 Offer II 090": { topicTags: ["array", "dynamic-programming"] },
+    "剑指 Offer II 091": { topicTags: ["array", "dynamic-programming"] },
+    "剑指 Offer II 092": { topicTags: ["string", "dynamic-programming"] },
+    "剑指 Offer II 093": {
+      topicTags: ["array", "hash-table", "dynamic-programming"],
+    },
+    "剑指 Offer II 094": { topicTags: ["string", "dynamic-programming"] },
+    "剑指 Offer II 095": { topicTags: ["string", "dynamic-programming"] },
+    "剑指 Offer II 096": { topicTags: ["string", "dynamic-programming"] },
+    "剑指 Offer II 097": { topicTags: ["string", "dynamic-programming"] },
+    "剑指 Offer II 098": {
+      topicTags: ["math", "dynamic-programming", "combinatorics"],
+    },
+    "剑指 Offer II 099": {
+      topicTags: ["array", "dynamic-programming", "matrix"],
+    },
+    "剑指 Offer II 100": { topicTags: ["array", "dynamic-programming"] },
+    "剑指 Offer II 101": { topicTags: ["math", "string", "simulation"] },
+    "剑指 Offer II 102": {
+      topicTags: ["array", "dynamic-programming", "backtracking"],
+    },
+    "剑指 Offer II 103": {
+      topicTags: ["breadth-first-search", "array", "dynamic-programming"],
+    },
+    "剑指 Offer II 104": { topicTags: ["array", "dynamic-programming"] },
+    "剑指 Offer II 105": {
+      topicTags: ["depth-first-search", "breadth-first-search", "union-find", "array", "matrix"],
+    },
+    "剑指 Offer II 106": {
+      topicTags: ["depth-first-search", "breadth-first-search", "union-find", "graph"],
+    },
+    "剑指 Offer II 107": {
+      topicTags: ["breadth-first-search", "array", "dynamic-programming", "matrix"],
+    },
+    "剑指 Offer II 108": {
+      topicTags: ["breadth-first-search", "hash-table", "string"],
+    },
+    "剑指 Offer II 109": {
+      topicTags: ["breadth-first-search", "array", "hash-table", "string"],
+    },
+    "剑指 Offer II 110": {
+      topicTags: ["depth-first-search", "breadth-first-search", "graph", "backtracking"],
+    },
+    "剑指 Offer II 111": {
+      topicTags: ["depth-first-search", "breadth-first-search", "union-find", "graph", "array", "shortest-path"],
+    },
+    "剑指 Offer II 112": {
+      topicTags: [
+        "depth-first-search",
+        "breadth-first-search",
+        "graph",
+        "topological-sort",
+        "memoization",
+        "array",
+        "dynamic-programming",
+        "matrix",
+      ],
+    },
+    "剑指 Offer II 113": {
+      topicTags: ["depth-first-search", "breadth-first-search", "graph", "topological-sort"],
+    },
+    "剑指 Offer II 114": {
+      topicTags: ["depth-first-search", "breadth-first-search", "graph", "topological-sort", "array", "string"],
+    },
+    "剑指 Offer II 115": { topicTags: ["graph", "topological-sort", "array"] },
+    "剑指 Offer II 116": {
+      topicTags: ["depth-first-search", "breadth-first-search", "union-find", "graph"],
+    },
+    "剑指 Offer II 117": {
+      topicTags: ["depth-first-search", "breadth-first-search", "union-find", "array", "string"],
+    },
+    "剑指 Offer II 118": {
+      topicTags: ["depth-first-search", "breadth-first-search", "union-find", "graph"],
+    },
+    "剑指 Offer II 119": { topicTags: ["union-find", "array", "hash-table"] },
+    "面试题 01.01": {
+      topicTags: ["bit-manipulation", "hash-table", "string", "sorting"],
+    },
+    "面试题 01.02": { topicTags: ["hash-table", "string", "sorting"] },
+    "面试题 01.03": { topicTags: ["string"] },
+    "面试题 01.04": { topicTags: ["bit-manipulation", "hash-table", "string"] },
+    "面试题 01.05": { topicTags: ["two-pointers", "string"] },
+    "面试题 01.06": { topicTags: ["two-pointers", "string"] },
+    "面试题 01.07": { topicTags: ["array", "math", "matrix"] },
+    "面试题 01.08": { topicTags: ["array", "hash-table", "matrix"] },
+    "面试题 01.09": { topicTags: ["string", "string-matching"] },
+    "面试题 02.01": {
+      topicTags: ["hash-table", "linked-list", "two-pointers"],
+    },
+    "面试题 02.02": { topicTags: ["linked-list", "two-pointers"] },
+    "面试题 02.03": { topicTags: ["linked-list"] },
+    "面试题 02.04": { topicTags: ["linked-list", "two-pointers"] },
+    "面试题 02.05": { topicTags: ["recursion", "linked-list", "math"] },
+    "面试题 02.06": {
+      topicTags: ["stack", "recursion", "linked-list", "two-pointers"],
+    },
+    "面试题 02.07": {
+      topicTags: ["hash-table", "linked-list", "two-pointers"],
+    },
+    "面试题 02.08": {
+      topicTags: ["hash-table", "linked-list", "two-pointers"],
+    },
+    "面试题 03.01": { topicTags: ["stack", "design", "array"] },
+    "面试题 03.02": { topicTags: ["stack", "design"] },
+    "面试题 03.03": { topicTags: ["stack", "design", "linked-list"] },
+    "面试题 03.04": { topicTags: ["stack", "design", "queue"] },
+    "面试题 03.05": { topicTags: ["stack", "design", "monotonic-stack"] },
+    "面试题 03.06": { topicTags: ["design", "queue"] },
+    "面试题 04.01": {
+      topicTags: ["depth-first-search", "breadth-first-search", "union-find", "graph"],
+    },
+    "面试题 04.02": {
+      topicTags: ["tree", "binary-search-tree", "array", "divide-and-conquer", "binary-tree"],
+    },
+    "面试题 04.03": {
+      topicTags: ["tree", "breadth-first-search", "linked-list", "binary-tree"],
+    },
+    "面试题 04.04": {
+      topicTags: ["tree", "depth-first-search", "binary-tree"],
+    },
+    "面试题 04.05": {
+      topicTags: ["tree", "depth-first-search", "binary-search-tree", "binary-tree"],
+    },
+    "面试题 04.06": {
+      topicTags: ["tree", "depth-first-search", "binary-search-tree", "binary-tree"],
+    },
+    "面试题 04.08": {
+      topicTags: ["tree", "depth-first-search", "binary-tree"],
+    },
+    "面试题 04.09": {
+      topicTags: ["tree", "binary-search-tree", "backtracking", "binary-tree"],
+    },
+    "面试题 04.10": {
+      topicTags: ["tree", "depth-first-search", "binary-tree", "string-matching", "hash-function"],
+    },
+    "面试题 04.12": {
+      topicTags: ["tree", "depth-first-search", "binary-tree"],
+    },
+    "面试题 05.01": { topicTags: ["bit-manipulation"] },
+    "面试题 05.02": { topicTags: ["bit-manipulation", "math", "string"] },
+    "面试题 05.03": { topicTags: ["bit-manipulation", "dynamic-programming"] },
+    "面试题 05.04": { topicTags: ["bit-manipulation"] },
+    "面试题 05.06": { topicTags: ["bit-manipulation"] },
+    "面试题 05.07": { topicTags: ["bit-manipulation"] },
+    "面试题 05.08": { topicTags: ["bit-manipulation", "array", "math"] },
+    "面试题 08.01": {
+      topicTags: ["memoization", "math", "dynamic-programming"],
+    },
+    "面试题 08.02": {
+      topicTags: ["array", "dynamic-programming", "backtracking", "matrix"],
+    },
+    "面试题 08.03": { topicTags: ["array", "binary-search"] },
+    "面试题 08.04": {
+      topicTags: ["bit-manipulation", "array", "backtracking"],
+    },
+    "面试题 08.05": { topicTags: ["bit-manipulation", "recursion", "math"] },
+    "面试题 08.06": { topicTags: ["recursion", "array"] },
+    "面试题 08.07": { topicTags: ["string", "backtracking"] },
+    "面试题 08.08": { topicTags: ["string", "backtracking"] },
+    "面试题 08.09": {
+      topicTags: ["string", "dynamic-programming", "backtracking"],
+    },
+    "面试题 08.10": {
+      topicTags: ["depth-first-search", "breadth-first-search", "array", "matrix"],
+    },
+    "面试题 08.11": { topicTags: ["array", "math", "dynamic-programming"] },
+    "面试题 08.12": { topicTags: ["array", "backtracking"] },
+    "面试题 08.13": { topicTags: ["array", "dynamic-programming", "sorting"] },
+    "面试题 08.14": {
+      topicTags: ["memoization", "string", "dynamic-programming"],
+    },
+    "面试题 10.01": { topicTags: ["array", "two-pointers", "sorting"] },
+    "面试题 10.02": { topicTags: ["array", "hash-table", "string", "sorting"] },
+    "面试题 10.03": { topicTags: ["array", "binary-search"] },
+    "面试题 10.05": { topicTags: ["array", "string", "binary-search"] },
+    "面试题 10.09": {
+      topicTags: ["array", "binary-search", "divide-and-conquer", "matrix"],
+    },
+    "面试题 10.10": {
+      topicTags: ["design", "binary-indexed-tree", "binary-search", "data-stream"],
+    },
+    "面试题 10.11": { topicTags: ["greedy", "array", "sorting"] },
+    "面试题 16.01": { topicTags: ["bit-manipulation", "math"] },
+    "面试题 16.02": {
+      topicTags: ["design", "trie", "array", "hash-table", "string"],
+    },
+    "面试题 16.03": { topicTags: ["geometry", "math"] },
+    "面试题 16.04": { topicTags: ["array", "counting", "matrix"] },
+    "面试题 16.05": { topicTags: ["math"] },
+    "面试题 16.06": {
+      topicTags: ["array", "two-pointers", "binary-search", "sorting"],
+    },
+    "面试题 16.07": { topicTags: ["bit-manipulation", "brainteaser", "math"] },
+    "面试题 16.08": { topicTags: ["recursion", "math", "string"] },
+    "面试题 16.09": { topicTags: ["design", "math"] },
+    "面试题 16.10": { topicTags: ["array", "counting"] },
+    "面试题 16.11": { topicTags: ["array", "math"] },
+    "面试题 16.13": { topicTags: ["geometry", "math"] },
+    "面试题 16.14": { topicTags: ["geometry", "array", "hash-table", "math"] },
+    "面试题 16.15": { topicTags: ["hash-table", "string", "counting"] },
+    "面试题 16.16": {
+      topicTags: ["stack", "greedy", "array", "two-pointers", "sorting", "monotonic-stack"],
+    },
+    "面试题 16.17": {
+      topicTags: ["array", "divide-and-conquer", "dynamic-programming"],
+    },
+    "面试题 16.18": {
+      topicTags: ["math", "string", "backtracking", "enumeration"],
+    },
+    "面试题 16.19": {
+      topicTags: ["depth-first-search", "breadth-first-search", "union-find", "array", "matrix"],
+    },
+    "面试题 16.20": { topicTags: ["array", "hash-table", "string"] },
+    "面试题 16.21": {
+      topicTags: ["array", "hash-table", "binary-search", "sorting"],
+    },
+    "面试题 16.22": {
+      topicTags: ["array", "hash-table", "string", "matrix", "simulation"],
+    },
+    "面试题 16.24": {
+      topicTags: ["array", "hash-table", "two-pointers", "counting", "sorting"],
+    },
+    "面试题 16.25": {
+      topicTags: ["design", "hash-table", "linked-list", "doubly-linked-list"],
+    },
+    "面试题 16.26": { topicTags: ["stack", "math", "string"] },
+    "面试题 17.01": { topicTags: ["bit-manipulation", "math"] },
+    "面试题 17.04": {
+      topicTags: ["bit-manipulation", "array", "hash-table", "math", "sorting"],
+    },
+    "面试题 17.05": { topicTags: ["array", "hash-table", "prefix-sum"] },
+    "面试题 17.06": { topicTags: ["recursion", "math", "dynamic-programming"] },
+    "面试题 17.07": {
+      topicTags: [
+        "depth-first-search",
+        "breadth-first-search",
+        "union-find",
+        "array",
+        "hash-table",
+        "string",
+        "counting",
+      ],
+    },
+    "面试题 17.08": {
+      topicTags: ["array", "binary-search", "dynamic-programming", "sorting"],
+    },
+    "面试题 17.09": {
+      topicTags: ["hash-table", "math", "dynamic-programming", "heap-priority-queue"],
+    },
+    "面试题 17.10": { topicTags: ["array", "counting"] },
+    "面试题 17.11": { topicTags: ["array", "string"] },
+    "面试题 17.12": {
+      topicTags: ["stack", "tree", "depth-first-search", "binary-search-tree", "linked-list", "binary-tree"],
+    },
+    "面试题 17.13": {
+      topicTags: ["trie", "array", "hash-table", "string", "dynamic-programming", "hash-function", "rolling-hash"],
+    },
+    "面试题 17.14": {
+      topicTags: ["array", "divide-and-conquer", "quickselect", "sorting", "heap-priority-queue"],
+    },
+    "面试题 17.15": { topicTags: ["trie", "array", "hash-table", "string"] },
+    "面试题 17.16": { topicTags: ["array", "dynamic-programming"] },
+    "面试题 17.17": {
+      topicTags: ["trie", "array", "hash-table", "string", "string-matching", "sliding-window"],
+    },
+    "面试题 17.18": { topicTags: ["array", "hash-table", "sliding-window"] },
+    "面试题 17.19": { topicTags: ["bit-manipulation", "array", "hash-table"] },
+    "面试题 17.20": {
+      topicTags: ["design", "two-pointers", "data-stream", "sorting", "heap-priority-queue"],
+    },
+    "面试题 17.21": {
+      topicTags: ["stack", "array", "two-pointers", "dynamic-programming", "monotonic-stack"],
+    },
+    "面试题 17.22": {
+      topicTags: ["breadth-first-search", "hash-table", "string", "backtracking"],
+    },
+    "面试题 17.23": { topicTags: ["array", "dynamic-programming", "matrix"] },
+    "面试题 17.24": {
+      topicTags: ["array", "dynamic-programming", "matrix", "prefix-sum"],
+    },
+    "面试题 17.25": { topicTags: ["trie", "array", "string", "backtracking"] },
+    "面试题 17.26": { topicTags: ["array", "hash-table", "sorting"] },
+    面试题13: {
+      topicTags: ["depth-first-search", "breadth-first-search", "dynamic-programming"],
+    },
+    "面试题59 - II": { topicTags: ["design", "queue", "monotonic-queue"] },
+  };
 
-    private tagsData = {
-        "1": { "topicTags": ["array", "hash-table"] },
-        "2": { "topicTags": ["recursion", "linked-list", "math"] },
-        "3": { "topicTags": ["hash-table", "string", "sliding-window"] },
-        "4": { "topicTags": ["array", "binary-search", "divide-and-conquer"] },
-        "5": { "topicTags": ["string", "dynamic-programming"] },
-        "6": { "topicTags": ["string"] },
-        "7": { "topicTags": ["math"] },
-        "8": { "topicTags": ["string"] },
-        "9": { "topicTags": ["math"] },
-        "10": { "topicTags": ["recursion", "string", "dynamic-programming"] },
-        "11": { "topicTags": ["greedy", "array", "two-pointers"] },
-        "12": { "topicTags": ["hash-table", "math", "string"] },
-        "13": { "topicTags": ["hash-table", "math", "string"] },
-        "14": { "topicTags": ["string"] },
-        "15": { "topicTags": ["array", "two-pointers", "sorting"] },
-        "16": { "topicTags": ["array", "two-pointers", "sorting"] },
-        "17": { "topicTags": ["hash-table", "string", "backtracking"] },
-        "18": { "topicTags": ["array", "two-pointers", "sorting"] },
-        "19": { "topicTags": ["linked-list", "two-pointers"] },
-        "20": { "topicTags": ["stack", "string"] },
-        "21": { "topicTags": ["recursion", "linked-list"] },
-        "22": { "topicTags": ["string", "dynamic-programming", "backtracking"] },
-        "23": { "topicTags": ["linked-list", "divide-and-conquer", "heap-priority-queue", "merge-sort"] },
-        "24": { "topicTags": ["recursion", "linked-list"] },
-        "25": { "topicTags": ["recursion", "linked-list"] },
-        "26": { "topicTags": ["array", "two-pointers"] },
-        "27": { "topicTags": ["array", "two-pointers"] },
-        "28": { "topicTags": ["two-pointers", "string", "string-matching"] },
-        "29": { "topicTags": ["bit-manipulation", "math"] },
-        "30": { "topicTags": ["hash-table", "string", "sliding-window"] },
-        "31": { "topicTags": ["array", "two-pointers"] },
-        "32": { "topicTags": ["stack", "string", "dynamic-programming"] },
-        "33": { "topicTags": ["array", "binary-search"] },
-        "34": { "topicTags": ["array", "binary-search"] },
-        "35": { "topicTags": ["array", "binary-search"] },
-        "36": { "topicTags": ["array", "hash-table", "matrix"] },
-        "37": { "topicTags": ["array", "backtracking", "matrix"] },
-        "38": { "topicTags": ["string"] },
-        "39": { "topicTags": ["array", "backtracking"] },
-        "40": { "topicTags": ["array", "backtracking"] },
-        "41": { "topicTags": ["array", "hash-table"] },
-        "42": { "topicTags": ["stack", "array", "two-pointers", "dynamic-programming", "monotonic-stack"] },
-        "43": { "topicTags": ["math", "string", "simulation"] },
-        "44": { "topicTags": ["greedy", "recursion", "string", "dynamic-programming"] },
-        "45": { "topicTags": ["greedy", "array", "dynamic-programming"] },
-        "46": { "topicTags": ["array", "backtracking"] },
-        "47": { "topicTags": ["array", "backtracking"] },
-        "48": { "topicTags": ["array", "math", "matrix"] },
-        "49": { "topicTags": ["array", "hash-table", "string", "sorting"] },
-        "50": { "topicTags": ["recursion", "math"] },
-        "51": { "topicTags": ["array", "backtracking"] },
-        "52": { "topicTags": ["backtracking"] },
-        "53": { "topicTags": ["array", "divide-and-conquer", "dynamic-programming"] },
-        "54": { "topicTags": ["array", "matrix", "simulation"] },
-        "55": { "topicTags": ["greedy", "array", "dynamic-programming"] },
-        "56": { "topicTags": ["array", "sorting"] },
-        "57": { "topicTags": ["array"] },
-        "58": { "topicTags": ["string"] },
-        "59": { "topicTags": ["array", "matrix", "simulation"] },
-        "60": { "topicTags": ["recursion", "math"] },
-        "61": { "topicTags": ["linked-list", "two-pointers"] },
-        "62": { "topicTags": ["math", "dynamic-programming", "combinatorics"] },
-        "63": { "topicTags": ["array", "dynamic-programming", "matrix"] },
-        "64": { "topicTags": ["array", "dynamic-programming", "matrix"] },
-        "65": { "topicTags": ["string"] },
-        "66": { "topicTags": ["array", "math"] },
-        "67": { "topicTags": ["bit-manipulation", "math", "string", "simulation"] },
-        "68": { "topicTags": ["array", "string", "simulation"] },
-        "69": { "topicTags": ["math", "binary-search"] },
-        "70": { "topicTags": ["memoization", "math", "dynamic-programming"] },
-        "71": { "topicTags": ["stack", "string"] },
-        "72": { "topicTags": ["string", "dynamic-programming"] },
-        "73": { "topicTags": ["array", "hash-table", "matrix"] },
-        "74": { "topicTags": ["array", "binary-search", "matrix"] },
-        "75": { "topicTags": ["array", "two-pointers", "sorting"] },
-        "76": { "topicTags": ["hash-table", "string", "sliding-window"] },
-        "77": { "topicTags": ["backtracking"] },
-        "78": { "topicTags": ["bit-manipulation", "array", "backtracking"] },
-        "79": { "topicTags": ["array", "backtracking", "matrix"] },
-        "80": { "topicTags": ["array", "two-pointers"] },
-        "81": { "topicTags": ["array", "binary-search"] },
-        "82": { "topicTags": ["linked-list", "two-pointers"] },
-        "83": { "topicTags": ["linked-list"] },
-        "84": { "topicTags": ["stack", "array", "monotonic-stack"] },
-        "85": { "topicTags": ["stack", "array", "dynamic-programming", "matrix", "monotonic-stack"] },
-        "86": { "topicTags": ["linked-list", "two-pointers"] },
-        "87": { "topicTags": ["string", "dynamic-programming"] },
-        "88": { "topicTags": ["array", "two-pointers", "sorting"] },
-        "89": { "topicTags": ["bit-manipulation", "math", "backtracking"] },
-        "90": { "topicTags": ["bit-manipulation", "array", "backtracking"] },
-        "91": { "topicTags": ["string", "dynamic-programming"] },
-        "92": { "topicTags": ["linked-list"] },
-        "93": { "topicTags": ["string", "backtracking"] },
-        "94": { "topicTags": ["stack", "tree", "depth-first-search", "binary-tree"] },
-        "95": { "topicTags": ["tree", "binary-search-tree", "dynamic-programming", "backtracking", "binary-tree"] },
-        "96": { "topicTags": ["tree", "binary-search-tree", "math", "dynamic-programming", "binary-tree"] },
-        "97": { "topicTags": ["string", "dynamic-programming"] },
-        "98": { "topicTags": ["tree", "depth-first-search", "binary-search-tree", "binary-tree"] },
-        "99": { "topicTags": ["tree", "depth-first-search", "binary-search-tree", "binary-tree"] },
-        "100": { "topicTags": ["tree", "depth-first-search", "breadth-first-search", "binary-tree"] },
-        "101": { "topicTags": ["tree", "depth-first-search", "breadth-first-search", "binary-tree"] },
-        "102": { "topicTags": ["tree", "breadth-first-search", "binary-tree"] },
-        "103": { "topicTags": ["tree", "breadth-first-search", "binary-tree"] },
-        "104": { "topicTags": ["tree", "depth-first-search", "breadth-first-search", "binary-tree"] },
-        "105": { "topicTags": ["tree", "array", "hash-table", "divide-and-conquer", "binary-tree"] },
-        "106": { "topicTags": ["tree", "array", "hash-table", "divide-and-conquer", "binary-tree"] },
-        "107": { "topicTags": ["tree", "breadth-first-search", "binary-tree"] },
-        "108": { "topicTags": ["tree", "binary-search-tree", "array", "divide-and-conquer", "binary-tree"] },
-        "109": { "topicTags": ["tree", "binary-search-tree", "linked-list", "divide-and-conquer", "binary-tree"] },
-        "110": { "topicTags": ["tree", "depth-first-search", "binary-tree"] },
-        "111": { "topicTags": ["tree", "depth-first-search", "breadth-first-search", "binary-tree"] },
-        "112": { "topicTags": ["tree", "depth-first-search", "breadth-first-search", "binary-tree"] },
-        "113": { "topicTags": ["tree", "depth-first-search", "backtracking", "binary-tree"] },
-        "114": { "topicTags": ["stack", "tree", "depth-first-search", "linked-list", "binary-tree"] },
-        "115": { "topicTags": ["string", "dynamic-programming"] },
-        "116": { "topicTags": ["tree", "depth-first-search", "breadth-first-search", "linked-list", "binary-tree"] },
-        "117": { "topicTags": ["tree", "depth-first-search", "breadth-first-search", "linked-list", "binary-tree"] },
-        "118": { "topicTags": ["array", "dynamic-programming"] },
-        "119": { "topicTags": ["array", "dynamic-programming"] },
-        "120": { "topicTags": ["array", "dynamic-programming"] },
-        "121": { "topicTags": ["array", "dynamic-programming"] },
-        "122": { "topicTags": ["greedy", "array", "dynamic-programming"] },
-        "123": { "topicTags": ["array", "dynamic-programming"] },
-        "124": { "topicTags": ["tree", "depth-first-search", "dynamic-programming", "binary-tree"] },
-        "125": { "topicTags": ["two-pointers", "string"] },
-        "126": { "topicTags": ["breadth-first-search", "hash-table", "string", "backtracking"] },
-        "127": { "topicTags": ["breadth-first-search", "hash-table", "string"] },
-        "128": { "topicTags": ["union-find", "array", "hash-table"] },
-        "129": { "topicTags": ["tree", "depth-first-search", "binary-tree"] },
-        "130": { "topicTags": ["depth-first-search", "breadth-first-search", "union-find", "array", "matrix"] },
-        "131": { "topicTags": ["string", "dynamic-programming", "backtracking"] },
-        "132": { "topicTags": ["string", "dynamic-programming"] },
-        "133": { "topicTags": ["depth-first-search", "breadth-first-search", "graph", "hash-table"] },
-        "134": { "topicTags": ["greedy", "array"] },
-        "135": { "topicTags": ["greedy", "array"] },
-        "136": { "topicTags": ["bit-manipulation", "array"] },
-        "137": { "topicTags": ["bit-manipulation", "array"] },
-        "138": { "topicTags": ["hash-table", "linked-list"] },
-        "139": { "topicTags": ["trie", "memoization", "hash-table", "string", "dynamic-programming"] },
-        "140": { "topicTags": ["trie", "memoization", "hash-table", "string", "dynamic-programming", "backtracking"] },
-        "141": { "topicTags": ["hash-table", "linked-list", "two-pointers"] },
-        "142": { "topicTags": ["hash-table", "linked-list", "two-pointers"] },
-        "143": { "topicTags": ["stack", "recursion", "linked-list", "two-pointers"] },
-        "144": { "topicTags": ["stack", "tree", "depth-first-search", "binary-tree"] },
-        "145": { "topicTags": ["stack", "tree", "depth-first-search", "binary-tree"] },
-        "146": { "topicTags": ["design", "hash-table", "linked-list", "doubly-linked-list"] },
-        "147": { "topicTags": ["linked-list", "sorting"] },
-        "148": { "topicTags": ["linked-list", "two-pointers", "divide-and-conquer", "sorting", "merge-sort"] },
-        "149": { "topicTags": ["geometry", "array", "hash-table", "math"] },
-        "150": { "topicTags": ["stack", "array", "math"] },
-        "151": { "topicTags": ["two-pointers", "string"] },
-        "152": { "topicTags": ["array", "dynamic-programming"] },
-        "153": { "topicTags": ["array", "binary-search"] },
-        "154": { "topicTags": ["array", "binary-search"] },
-        "155": { "topicTags": ["stack", "design"] },
-        "156": { "topicTags": ["tree", "depth-first-search", "binary-tree"] },
-        "157": { "topicTags": ["string", "interactive", "simulation"] },
-        "158": { "topicTags": ["string", "interactive", "simulation"] },
-        "159": { "topicTags": ["hash-table", "string", "sliding-window"] },
-        "160": { "topicTags": ["hash-table", "linked-list", "two-pointers"] },
-        "161": { "topicTags": ["two-pointers", "string"] },
-        "162": { "topicTags": ["array", "binary-search"] },
-        "163": { "topicTags": ["array"] },
-        "164": { "topicTags": ["array", "bucket-sort", "radix-sort", "sorting"] },
-        "165": { "topicTags": ["two-pointers", "string"] },
-        "166": { "topicTags": ["hash-table", "math", "string"] },
-        "167": { "topicTags": ["array", "two-pointers", "binary-search"] },
-        "168": { "topicTags": ["math", "string"] },
-        "169": { "topicTags": ["array", "hash-table", "divide-and-conquer", "counting", "sorting"] },
-        "170": { "topicTags": ["design", "array", "hash-table", "two-pointers", "data-stream"] },
-        "171": { "topicTags": ["math", "string"] },
-        "172": { "topicTags": ["math"] },
-        "173": { "topicTags": ["stack", "tree", "design", "binary-search-tree", "binary-tree", "iterator"] },
-        "174": { "topicTags": ["array", "dynamic-programming", "matrix"] },
-        "175": { "topicTags": ["database"] },
-        "176": { "topicTags": ["database"] },
-        "177": { "topicTags": ["database"] },
-        "178": { "topicTags": ["database"] },
-        "179": { "topicTags": ["greedy", "string", "sorting"] },
-        "180": { "topicTags": ["database"] },
-        "181": { "topicTags": ["database"] },
-        "182": { "topicTags": ["database"] },
-        "183": { "topicTags": ["database"] },
-        "184": { "topicTags": ["database"] },
-        "185": { "topicTags": ["database"] },
-        "186": { "topicTags": ["two-pointers", "string"] },
-        "187": { "topicTags": ["bit-manipulation", "hash-table", "string", "sliding-window", "hash-function", "rolling-hash"] },
-        "188": { "topicTags": ["array", "dynamic-programming"] },
-        "189": { "topicTags": ["array", "math", "two-pointers"] },
-        "190": { "topicTags": ["bit-manipulation", "divide-and-conquer"] },
-        "191": { "topicTags": ["bit-manipulation", "divide-and-conquer"] },
-        "192": { "topicTags": ["shell"] },
-        "193": { "topicTags": ["shell"] },
-        "194": { "topicTags": ["shell"] },
-        "195": { "topicTags": ["shell"] },
-        "196": { "topicTags": ["database"] },
-        "197": { "topicTags": ["database"] },
-        "198": { "topicTags": ["array", "dynamic-programming"] },
-        "199": { "topicTags": ["tree", "depth-first-search", "breadth-first-search", "binary-tree"] },
-        "200": { "topicTags": ["depth-first-search", "breadth-first-search", "union-find", "array", "matrix"] },
-        "201": { "topicTags": ["bit-manipulation"] },
-        "202": { "topicTags": ["hash-table", "math", "two-pointers"] },
-        "203": { "topicTags": ["recursion", "linked-list"] },
-        "204": { "topicTags": ["array", "math", "enumeration", "number-theory"] },
-        "205": { "topicTags": ["hash-table", "string"] },
-        "206": { "topicTags": ["recursion", "linked-list"] },
-        "207": { "topicTags": ["depth-first-search", "breadth-first-search", "graph", "topological-sort"] },
-        "208": { "topicTags": ["design", "trie", "hash-table", "string"] },
-        "209": { "topicTags": ["array", "binary-search", "prefix-sum", "sliding-window"] },
-        "210": { "topicTags": ["depth-first-search", "breadth-first-search", "graph", "topological-sort"] },
-        "211": { "topicTags": ["depth-first-search", "design", "trie", "string"] },
-        "212": { "topicTags": ["trie", "array", "string", "backtracking", "matrix"] },
-        "213": { "topicTags": ["array", "dynamic-programming"] },
-        "214": { "topicTags": ["string", "string-matching", "hash-function", "rolling-hash"] },
-        "215": { "topicTags": ["array", "divide-and-conquer", "quickselect", "sorting", "heap-priority-queue"] },
-        "216": { "topicTags": ["array", "backtracking"] },
-        "217": { "topicTags": ["array", "hash-table", "sorting"] },
-        "218": { "topicTags": ["binary-indexed-tree", "segment-tree", "array", "divide-and-conquer", "ordered-set", "line-sweep", "heap-priority-queue"] },
-        "219": { "topicTags": ["array", "hash-table", "sliding-window"] },
-        "220": { "topicTags": ["array", "bucket-sort", "ordered-set", "sorting", "sliding-window"] },
-        "221": { "topicTags": ["array", "dynamic-programming", "matrix"] },
-        "222": { "topicTags": ["tree", "depth-first-search", "binary-search", "binary-tree"] },
-        "223": { "topicTags": ["geometry", "math"] },
-        "224": { "topicTags": ["stack", "recursion", "math", "string"] },
-        "225": { "topicTags": ["stack", "design", "queue"] },
-        "226": { "topicTags": ["tree", "depth-first-search", "breadth-first-search", "binary-tree"] },
-        "227": { "topicTags": ["stack", "math", "string"] },
-        "228": { "topicTags": ["array"] },
-        "229": { "topicTags": ["array", "hash-table", "counting", "sorting"] },
-        "230": { "topicTags": ["tree", "depth-first-search", "binary-search-tree", "binary-tree"] },
-        "231": { "topicTags": ["bit-manipulation", "recursion", "math"] },
-        "232": { "topicTags": ["stack", "design", "queue"] },
-        "233": { "topicTags": ["recursion", "math", "dynamic-programming"] },
-        "234": { "topicTags": ["stack", "recursion", "linked-list", "two-pointers"] },
-        "235": { "topicTags": ["tree", "depth-first-search", "binary-search-tree", "binary-tree"] },
-        "236": { "topicTags": ["tree", "depth-first-search", "binary-tree"] },
-        "237": { "topicTags": ["linked-list"] },
-        "238": { "topicTags": ["array", "prefix-sum"] },
-        "239": { "topicTags": ["queue", "array", "sliding-window", "monotonic-queue", "heap-priority-queue"] },
-        "240": { "topicTags": ["array", "binary-search", "divide-and-conquer", "matrix"] },
-        "241": { "topicTags": ["recursion", "memoization", "math", "string", "dynamic-programming"] },
-        "242": { "topicTags": ["hash-table", "string", "sorting"] },
-        "243": { "topicTags": ["array", "string"] },
-        "244": { "topicTags": ["design", "array", "hash-table", "two-pointers", "string"] },
-        "245": { "topicTags": ["array", "string"] },
-        "246": { "topicTags": ["hash-table", "two-pointers", "string"] },
-        "247": { "topicTags": ["recursion", "array", "string"] },
-        "248": { "topicTags": ["recursion", "array", "string"] },
-        "249": { "topicTags": ["array", "hash-table", "string"] },
-        "250": { "topicTags": ["tree", "depth-first-search", "binary-tree"] },
-        "251": { "topicTags": ["design", "array", "two-pointers", "iterator"] },
-        "252": { "topicTags": ["array", "sorting"] },
-        "253": { "topicTags": ["greedy", "array", "two-pointers", "prefix-sum", "sorting", "heap-priority-queue"] },
-        "254": { "topicTags": ["array", "backtracking"] },
-        "255": { "topicTags": ["stack", "tree", "binary-search-tree", "recursion", "binary-tree", "monotonic-stack"] },
-        "256": { "topicTags": ["array", "dynamic-programming"] },
-        "257": { "topicTags": ["tree", "depth-first-search", "string", "backtracking", "binary-tree"] },
-        "258": { "topicTags": ["math", "number-theory", "simulation"] },
-        "259": { "topicTags": ["array", "two-pointers", "binary-search", "sorting"] },
-        "260": { "topicTags": ["bit-manipulation", "array"] },
-        "261": { "topicTags": ["depth-first-search", "breadth-first-search", "union-find", "graph"] },
-        "262": { "topicTags": ["database"] },
-        "263": { "topicTags": ["math"] },
-        "264": { "topicTags": ["hash-table", "math", "dynamic-programming", "heap-priority-queue"] },
-        "265": { "topicTags": ["array", "dynamic-programming"] },
-        "266": { "topicTags": ["bit-manipulation", "hash-table", "string"] },
-        "267": { "topicTags": ["hash-table", "string", "backtracking"] },
-        "268": { "topicTags": ["bit-manipulation", "array", "hash-table", "math", "binary-search", "sorting"] },
-        "269": { "topicTags": ["depth-first-search", "breadth-first-search", "graph", "topological-sort", "array", "string"] },
-        "270": { "topicTags": ["tree", "depth-first-search", "binary-search-tree", "binary-search", "binary-tree"] },
-        "271": { "topicTags": ["design", "array", "string"] },
-        "272": { "topicTags": ["stack", "tree", "depth-first-search", "binary-search-tree", "two-pointers", "binary-tree", "heap-priority-queue"] },
-        "273": { "topicTags": ["recursion", "math", "string"] },
-        "274": { "topicTags": ["array", "counting-sort", "sorting"] },
-        "275": { "topicTags": ["array", "binary-search"] },
-        "276": { "topicTags": ["dynamic-programming"] },
-        "277": { "topicTags": ["greedy", "graph", "two-pointers", "interactive"] },
-        "278": { "topicTags": ["binary-search", "interactive"] },
-        "279": { "topicTags": ["breadth-first-search", "math", "dynamic-programming"] },
-        "280": { "topicTags": ["greedy", "array", "sorting"] },
-        "281": { "topicTags": ["design", "queue", "array", "iterator"] },
-        "282": { "topicTags": ["math", "string", "backtracking"] },
-        "283": { "topicTags": ["array", "two-pointers"] },
-        "284": { "topicTags": ["design", "array", "iterator"] },
-        "285": { "topicTags": ["tree", "depth-first-search", "binary-search-tree", "binary-tree"] },
-        "286": { "topicTags": ["breadth-first-search", "array", "matrix"] },
-        "287": { "topicTags": ["bit-manipulation", "array", "two-pointers", "binary-search"] },
-        "288": { "topicTags": ["design", "array", "hash-table", "string"] },
-        "289": { "topicTags": ["array", "matrix", "simulation"] },
-        "290": { "topicTags": ["hash-table", "string"] },
-        "291": { "topicTags": ["hash-table", "string", "backtracking"] },
-        "292": { "topicTags": ["brainteaser", "math", "game-theory"] },
-        "293": { "topicTags": ["string"] },
-        "294": { "topicTags": ["memoization", "math", "dynamic-programming", "backtracking", "game-theory"] },
-        "295": { "topicTags": ["design", "two-pointers", "data-stream", "sorting", "heap-priority-queue"] },
-        "296": { "topicTags": ["array", "math", "matrix", "sorting"] },
-        "297": { "topicTags": ["tree", "depth-first-search", "breadth-first-search", "design", "string", "binary-tree"] },
-        "298": { "topicTags": ["tree", "depth-first-search", "binary-tree"] },
-        "299": { "topicTags": ["hash-table", "string", "counting"] },
-        "300": { "topicTags": ["array", "binary-search", "dynamic-programming"] },
-        "301": { "topicTags": ["breadth-first-search", "string", "backtracking"] },
-        "302": { "topicTags": ["depth-first-search", "breadth-first-search", "array", "binary-search", "matrix"] },
-        "303": { "topicTags": ["design", "array", "prefix-sum"] },
-        "304": { "topicTags": ["design", "array", "matrix", "prefix-sum"] },
-        "305": { "topicTags": ["union-find", "array"] },
-        "306": { "topicTags": ["string", "backtracking"] },
-        "307": { "topicTags": ["design", "binary-indexed-tree", "segment-tree", "array"] },
-        "308": { "topicTags": ["design", "binary-indexed-tree", "segment-tree", "array", "matrix"] },
-        "309": { "topicTags": ["array", "dynamic-programming"] },
-        "310": { "topicTags": ["depth-first-search", "breadth-first-search", "graph", "topological-sort"] },
-        "311": { "topicTags": ["array", "hash-table", "matrix"] },
-        "312": { "topicTags": ["array", "dynamic-programming"] },
-        "313": { "topicTags": ["array", "math", "dynamic-programming"] },
-        "314": { "topicTags": ["tree", "depth-first-search", "breadth-first-search", "hash-table", "binary-tree"] },
-        "315": { "topicTags": ["binary-indexed-tree", "segment-tree", "array", "binary-search", "divide-and-conquer", "ordered-set", "merge-sort"] },
-        "316": { "topicTags": ["stack", "greedy", "string", "monotonic-stack"] },
-        "317": { "topicTags": ["breadth-first-search", "array", "matrix"] },
-        "318": { "topicTags": ["bit-manipulation", "array", "string"] },
-        "319": { "topicTags": ["brainteaser", "math"] },
-        "320": { "topicTags": ["bit-manipulation", "string", "backtracking"] },
-        "321": { "topicTags": ["stack", "greedy", "monotonic-stack"] },
-        "322": { "topicTags": ["breadth-first-search", "array", "dynamic-programming"] },
-        "323": { "topicTags": ["depth-first-search", "breadth-first-search", "union-find", "graph"] },
-        "324": { "topicTags": ["array", "divide-and-conquer", "quickselect", "sorting"] },
-        "325": { "topicTags": ["array", "hash-table"] },
-        "326": { "topicTags": ["recursion", "math"] },
-        "327": { "topicTags": ["binary-indexed-tree", "segment-tree", "array", "binary-search", "divide-and-conquer", "ordered-set", "merge-sort"] },
-        "328": { "topicTags": ["linked-list"] },
-        "329": { "topicTags": ["depth-first-search", "breadth-first-search", "graph", "topological-sort", "memoization", "array", "dynamic-programming", "matrix"] },
-        "330": { "topicTags": ["greedy", "array"] },
-        "331": { "topicTags": ["stack", "tree", "string", "binary-tree"] },
-        "332": { "topicTags": ["depth-first-search", "graph", "eulerian-circuit"] },
-        "333": { "topicTags": ["tree", "depth-first-search", "binary-search-tree", "dynamic-programming", "binary-tree"] },
-        "334": { "topicTags": ["greedy", "array"] },
-        "335": { "topicTags": ["geometry", "array", "math"] },
-        "336": { "topicTags": ["trie", "array", "hash-table", "string"] },
-        "337": { "topicTags": ["tree", "depth-first-search", "dynamic-programming", "binary-tree"] },
-        "338": { "topicTags": ["bit-manipulation", "dynamic-programming"] },
-        "339": { "topicTags": ["depth-first-search", "breadth-first-search"] },
-        "340": { "topicTags": ["hash-table", "string", "sliding-window"] },
-        "341": { "topicTags": ["stack", "tree", "depth-first-search", "design", "queue", "iterator"] },
-        "342": { "topicTags": ["bit-manipulation", "recursion", "math"] },
-        "343": { "topicTags": ["math", "dynamic-programming"] },
-        "344": { "topicTags": ["recursion", "two-pointers", "string"] },
-        "345": { "topicTags": ["two-pointers", "string"] },
-        "346": { "topicTags": ["design", "queue", "array", "data-stream"] },
-        "347": { "topicTags": ["array", "hash-table", "divide-and-conquer", "bucket-sort", "counting", "quickselect", "sorting", "heap-priority-queue"] },
-        "348": { "topicTags": ["design", "array", "hash-table", "matrix"] },
-        "349": { "topicTags": ["array", "hash-table", "two-pointers", "binary-search", "sorting"] },
-        "350": { "topicTags": ["array", "hash-table", "two-pointers", "binary-search", "sorting"] },
-        "351": { "topicTags": ["dynamic-programming", "backtracking"] },
-        "352": { "topicTags": ["design", "binary-search", "ordered-set"] },
-        "353": { "topicTags": ["design", "queue", "array", "matrix"] },
-        "354": { "topicTags": ["array", "binary-search", "dynamic-programming", "sorting"] },
-        "355": { "topicTags": ["design", "hash-table", "linked-list", "heap-priority-queue"] },
-        "356": { "topicTags": ["array", "hash-table", "math"] },
-        "357": { "topicTags": ["math", "dynamic-programming", "backtracking"] },
-        "358": { "topicTags": ["greedy", "hash-table", "string", "counting", "sorting", "heap-priority-queue"] },
-        "359": { "topicTags": ["design", "hash-table"] },
-        "360": { "topicTags": ["array", "math", "two-pointers", "sorting"] },
-        "361": { "topicTags": ["array", "dynamic-programming", "matrix"] },
-        "362": { "topicTags": ["design", "queue", "array", "hash-table", "binary-search"] },
-        "363": { "topicTags": ["array", "binary-search", "matrix", "ordered-set", "prefix-sum"] },
-        "364": { "topicTags": ["stack", "depth-first-search", "breadth-first-search"] },
-        "365": { "topicTags": ["depth-first-search", "breadth-first-search", "math"] },
-        "366": { "topicTags": ["tree", "depth-first-search", "binary-tree"] },
-        "367": { "topicTags": ["math", "binary-search"] },
-        "368": { "topicTags": ["array", "math", "dynamic-programming", "sorting"] },
-        "369": { "topicTags": ["linked-list", "math"] },
-        "370": { "topicTags": ["array", "prefix-sum"] },
-        "371": { "topicTags": ["bit-manipulation", "math"] },
-        "372": { "topicTags": ["math", "divide-and-conquer"] },
-        "373": { "topicTags": ["array", "heap-priority-queue"] },
-        "374": { "topicTags": ["binary-search", "interactive"] },
-        "375": { "topicTags": ["math", "dynamic-programming", "game-theory"] },
-        "376": { "topicTags": ["greedy", "array", "dynamic-programming"] },
-        "377": { "topicTags": ["array", "dynamic-programming"] },
-        "378": { "topicTags": ["array", "binary-search", "matrix", "sorting", "heap-priority-queue"] },
-        "379": { "topicTags": ["design", "queue", "array", "hash-table", "linked-list"] },
-        "380": { "topicTags": ["design", "array", "hash-table", "math", "randomized"] },
-        "381": { "topicTags": ["design", "array", "hash-table", "math", "randomized"] },
-        "382": { "topicTags": ["reservoir-sampling", "linked-list", "math", "randomized"] },
-        "383": { "topicTags": ["hash-table", "string", "counting"] },
-        "384": { "topicTags": ["array", "math", "randomized"] },
-        "385": { "topicTags": ["stack", "depth-first-search", "string"] },
-        "386": { "topicTags": ["depth-first-search", "trie"] },
-        "387": { "topicTags": ["queue", "hash-table", "string", "counting"] },
-        "388": { "topicTags": ["stack", "depth-first-search", "string"] },
-        "389": { "topicTags": ["bit-manipulation", "hash-table", "string", "sorting"] },
-        "390": { "topicTags": ["recursion", "math"] },
-        "391": { "topicTags": ["array", "line-sweep"] },
-        "392": { "topicTags": ["two-pointers", "string", "dynamic-programming"] },
-        "393": { "topicTags": ["bit-manipulation", "array"] },
-        "394": { "topicTags": ["stack", "recursion", "string"] },
-        "395": { "topicTags": ["hash-table", "string", "divide-and-conquer", "sliding-window"] },
-        "396": { "topicTags": ["array", "math", "dynamic-programming"] },
-        "397": { "topicTags": ["greedy", "bit-manipulation", "memoization", "dynamic-programming"] },
-        "398": { "topicTags": ["reservoir-sampling", "hash-table", "math", "randomized"] },
-        "399": { "topicTags": ["depth-first-search", "breadth-first-search", "union-find", "graph", "array", "shortest-path"] },
-        "400": { "topicTags": ["math", "binary-search"] },
-        "401": { "topicTags": ["bit-manipulation", "backtracking"] },
-        "402": { "topicTags": ["stack", "greedy", "string", "monotonic-stack"] },
-        "403": { "topicTags": ["array", "dynamic-programming"] },
-        "404": { "topicTags": ["tree", "depth-first-search", "breadth-first-search", "binary-tree"] },
-        "405": { "topicTags": ["bit-manipulation", "math"] },
-        "406": { "topicTags": ["greedy", "binary-indexed-tree", "segment-tree", "array", "sorting"] },
-        "407": { "topicTags": ["breadth-first-search", "array", "matrix", "heap-priority-queue"] },
-        "408": { "topicTags": ["two-pointers", "string"] },
-        "409": { "topicTags": ["greedy", "hash-table", "string"] },
-        "410": { "topicTags": ["greedy", "array", "binary-search", "dynamic-programming"] },
-        "411": { "topicTags": ["bit-manipulation", "string", "backtracking"] },
-        "412": { "topicTags": ["math", "string", "simulation"] },
-        "413": { "topicTags": ["array", "dynamic-programming"] },
-        "414": { "topicTags": ["array", "sorting"] },
-        "415": { "topicTags": ["math", "string", "simulation"] },
-        "416": { "topicTags": ["array", "dynamic-programming"] },
-        "417": { "topicTags": ["depth-first-search", "breadth-first-search", "array", "matrix"] },
-        "418": { "topicTags": ["string", "dynamic-programming", "simulation"] },
-        "419": { "topicTags": ["depth-first-search", "array", "matrix"] },
-        "420": { "topicTags": ["greedy", "string", "heap-priority-queue"] },
-        "421": { "topicTags": ["bit-manipulation", "trie", "array", "hash-table"] },
-        "422": { "topicTags": ["array", "matrix"] },
-        "423": { "topicTags": ["hash-table", "math", "string"] },
-        "424": { "topicTags": ["hash-table", "string", "sliding-window"] },
-        "425": { "topicTags": ["trie", "array", "string", "backtracking"] },
-        "426": { "topicTags": ["stack", "tree", "depth-first-search", "binary-search-tree", "linked-list", "binary-tree", "doubly-linked-list"] },
-        "427": { "topicTags": ["tree", "array", "divide-and-conquer", "matrix"] },
-        "428": { "topicTags": ["tree", "depth-first-search", "breadth-first-search", "string"] },
-        "429": { "topicTags": ["tree", "breadth-first-search"] },
-        "430": { "topicTags": ["depth-first-search", "linked-list", "doubly-linked-list"] },
-        "431": { "topicTags": ["tree", "depth-first-search", "breadth-first-search", "design", "binary-tree"] },
-        "432": { "topicTags": ["design", "hash-table", "linked-list", "doubly-linked-list"] },
-        "433": { "topicTags": ["breadth-first-search", "hash-table", "string"] },
-        "434": { "topicTags": ["string"] },
-        "435": { "topicTags": ["greedy", "array", "dynamic-programming", "sorting"] },
-        "436": { "topicTags": ["array", "binary-search", "sorting"] },
-        "437": { "topicTags": ["tree", "depth-first-search", "binary-tree"] },
-        "438": { "topicTags": ["hash-table", "string", "sliding-window"] },
-        "439": { "topicTags": ["stack", "recursion", "string"] },
-        "440": { "topicTags": ["trie"] },
-        "441": { "topicTags": ["math", "binary-search"] },
-        "442": { "topicTags": ["array", "hash-table"] },
-        "443": { "topicTags": ["two-pointers", "string"] },
-        "444": { "topicTags": ["graph", "topological-sort", "array"] },
-        "445": { "topicTags": ["stack", "linked-list", "math"] },
-        "446": { "topicTags": ["array", "dynamic-programming"] },
-        "447": { "topicTags": ["array", "hash-table", "math"] },
-        "448": { "topicTags": ["array", "hash-table"] },
-        "449": { "topicTags": ["tree", "depth-first-search", "breadth-first-search", "design", "binary-search-tree", "string", "binary-tree"] },
-        "450": { "topicTags": ["tree", "binary-search-tree", "binary-tree"] },
-        "451": { "topicTags": ["hash-table", "string", "bucket-sort", "counting", "sorting", "heap-priority-queue"] },
-        "452": { "topicTags": ["greedy", "array", "sorting"] },
-        "453": { "topicTags": ["array", "math"] },
-        "454": { "topicTags": ["array", "hash-table"] },
-        "455": { "topicTags": ["greedy", "array", "two-pointers", "sorting"] },
-        "456": { "topicTags": ["stack", "array", "binary-search", "ordered-set", "monotonic-stack"] },
-        "457": { "topicTags": ["array", "hash-table", "two-pointers"] },
-        "458": { "topicTags": ["math", "dynamic-programming", "combinatorics"] },
-        "459": { "topicTags": ["string", "string-matching"] },
-        "460": { "topicTags": ["design", "hash-table", "linked-list", "doubly-linked-list"] },
-        "461": { "topicTags": ["bit-manipulation"] },
-        "462": { "topicTags": ["array", "math", "sorting"] },
-        "463": { "topicTags": ["depth-first-search", "breadth-first-search", "array", "matrix"] },
-        "464": { "topicTags": ["bit-manipulation", "memoization", "math", "dynamic-programming", "bitmask", "game-theory"] },
-        "465": { "topicTags": ["bit-manipulation", "array", "dynamic-programming", "backtracking", "bitmask"] },
-        "466": { "topicTags": ["string", "dynamic-programming"] },
-        "467": { "topicTags": ["string", "dynamic-programming"] },
-        "468": { "topicTags": ["string"] },
-        "469": { "topicTags": ["geometry", "math"] },
-        "470": { "topicTags": ["math", "rejection-sampling", "probability-and-statistics", "randomized"] },
-        "471": { "topicTags": ["string", "dynamic-programming"] },
-        "472": { "topicTags": ["depth-first-search", "trie", "array", "string", "dynamic-programming"] },
-        "473": { "topicTags": ["bit-manipulation", "array", "dynamic-programming", "backtracking", "bitmask"] },
-        "474": { "topicTags": ["array", "string", "dynamic-programming"] },
-        "475": { "topicTags": ["array", "two-pointers", "binary-search", "sorting"] },
-        "476": { "topicTags": ["bit-manipulation"] },
-        "477": { "topicTags": ["bit-manipulation", "array", "math"] },
-        "478": { "topicTags": ["geometry", "math", "rejection-sampling", "randomized"] },
-        "479": { "topicTags": ["math"] },
-        "480": { "topicTags": ["array", "hash-table", "sliding-window", "heap-priority-queue"] },
-        "481": { "topicTags": ["two-pointers", "string"] },
-        "482": { "topicTags": ["string"] },
-        "483": { "topicTags": ["math", "binary-search"] },
-        "484": { "topicTags": ["stack", "greedy", "array", "string"] },
-        "485": { "topicTags": ["array"] },
-        "486": { "topicTags": ["recursion", "array", "math", "dynamic-programming", "game-theory"] },
-        "487": { "topicTags": ["array", "dynamic-programming", "sliding-window"] },
-        "488": { "topicTags": ["breadth-first-search", "memoization", "string", "dynamic-programming"] },
-        "489": { "topicTags": ["backtracking", "interactive"] },
-        "490": { "topicTags": ["depth-first-search", "breadth-first-search", "graph"] },
-        "491": { "topicTags": ["bit-manipulation", "array", "hash-table", "backtracking"] },
-        "492": { "topicTags": ["math"] },
-        "493": { "topicTags": ["binary-indexed-tree", "segment-tree", "array", "binary-search", "divide-and-conquer", "ordered-set", "merge-sort"] },
-        "494": { "topicTags": ["array", "dynamic-programming", "backtracking"] },
-        "495": { "topicTags": ["array", "simulation"] },
-        "496": { "topicTags": ["stack", "array", "hash-table", "monotonic-stack"] },
-        "497": { "topicTags": ["reservoir-sampling", "math", "binary-search", "ordered-set", "prefix-sum", "randomized"] },
-        "498": { "topicTags": ["array", "matrix", "simulation"] },
-        "499": { "topicTags": ["depth-first-search", "breadth-first-search", "graph", "shortest-path", "heap-priority-queue"] },
-        "500": { "topicTags": ["array", "hash-table", "string"] },
-        "501": { "topicTags": ["tree", "depth-first-search", "binary-search-tree", "binary-tree"] },
-        "502": { "topicTags": ["greedy", "array", "sorting", "heap-priority-queue"] },
-        "503": { "topicTags": ["stack", "array", "monotonic-stack"] },
-        "504": { "topicTags": ["math"] },
-        "505": { "topicTags": ["depth-first-search", "breadth-first-search", "graph", "shortest-path", "heap-priority-queue"] },
-        "506": { "topicTags": ["array", "sorting", "heap-priority-queue"] },
-        "507": { "topicTags": ["math"] },
-        "508": { "topicTags": ["tree", "depth-first-search", "hash-table", "binary-tree"] },
-        "509": { "topicTags": ["recursion", "memoization", "math", "dynamic-programming"] },
-        "510": { "topicTags": ["tree", "binary-search-tree", "binary-tree"] },
-        "511": { "topicTags": ["database"] },
-        "512": { "topicTags": ["database"] },
-        "513": { "topicTags": ["tree", "depth-first-search", "breadth-first-search", "binary-tree"] },
-        "514": { "topicTags": ["depth-first-search", "breadth-first-search", "string", "dynamic-programming"] },
-        "515": { "topicTags": ["tree", "depth-first-search", "breadth-first-search", "binary-tree"] },
-        "516": { "topicTags": ["string", "dynamic-programming"] },
-        "517": { "topicTags": ["greedy", "array"] },
-        "518": { "topicTags": ["array", "dynamic-programming"] },
-        "519": { "topicTags": ["reservoir-sampling", "hash-table", "math", "randomized"] },
-        "520": { "topicTags": ["string"] },
-        "521": { "topicTags": ["string"] },
-        "522": { "topicTags": ["array", "hash-table", "two-pointers", "string", "sorting"] },
-        "523": { "topicTags": ["array", "hash-table", "math", "prefix-sum"] },
-        "524": { "topicTags": ["array", "two-pointers", "string", "sorting"] },
-        "525": { "topicTags": ["array", "hash-table", "prefix-sum"] },
-        "526": { "topicTags": ["bit-manipulation", "array", "dynamic-programming", "backtracking", "bitmask"] },
-        "527": { "topicTags": ["greedy", "trie", "array", "string", "sorting"] },
-        "528": { "topicTags": ["math", "binary-search", "prefix-sum", "randomized"] },
-        "529": { "topicTags": ["depth-first-search", "breadth-first-search", "array", "matrix"] },
-        "530": { "topicTags": ["tree", "depth-first-search", "breadth-first-search", "binary-search-tree", "binary-tree"] },
-        "531": { "topicTags": ["array", "hash-table", "matrix"] },
-        "532": { "topicTags": ["array", "hash-table", "two-pointers", "binary-search", "sorting"] },
-        "533": { "topicTags": ["array", "hash-table", "matrix"] },
-        "534": { "topicTags": ["database"] },
-        "535": { "topicTags": ["design", "hash-table", "string", "hash-function"] },
-        "536": { "topicTags": ["tree", "depth-first-search", "string", "binary-tree"] },
-        "537": { "topicTags": ["math", "string", "simulation"] },
-        "538": { "topicTags": ["tree", "depth-first-search", "binary-search-tree", "binary-tree"] },
-        "539": { "topicTags": ["array", "math", "string", "sorting"] },
-        "540": { "topicTags": ["array", "binary-search"] },
-        "541": { "topicTags": ["two-pointers", "string"] },
-        "542": { "topicTags": ["breadth-first-search", "array", "dynamic-programming", "matrix"] },
-        "543": { "topicTags": ["tree", "depth-first-search", "binary-tree"] },
-        "544": { "topicTags": ["recursion", "string", "simulation"] },
-        "545": { "topicTags": ["tree", "depth-first-search", "binary-tree"] },
-        "546": { "topicTags": ["memoization", "array", "dynamic-programming"] },
-        "547": { "topicTags": ["depth-first-search", "breadth-first-search", "union-find", "graph"] },
-        "548": { "topicTags": ["array", "prefix-sum"] },
-        "549": { "topicTags": ["tree", "depth-first-search", "binary-tree"] },
-        "550": { "topicTags": ["database"] },
-        "551": { "topicTags": ["string"] },
-        "552": { "topicTags": ["dynamic-programming"] },
-        "553": { "topicTags": ["array", "math", "dynamic-programming"] },
-        "554": { "topicTags": ["array", "hash-table"] },
-        "555": { "topicTags": ["greedy", "array", "string"] },
-        "556": { "topicTags": ["math", "two-pointers", "string"] },
-        "557": { "topicTags": ["two-pointers", "string"] },
-        "558": { "topicTags": ["tree", "divide-and-conquer"] },
-        "559": { "topicTags": ["tree", "depth-first-search", "breadth-first-search"] },
-        "560": { "topicTags": ["array", "hash-table", "prefix-sum"] },
-        "561": { "topicTags": ["greedy", "array", "counting-sort", "sorting"] },
-        "562": { "topicTags": ["array", "dynamic-programming", "matrix"] },
-        "563": { "topicTags": ["tree", "depth-first-search", "binary-tree"] },
-        "564": { "topicTags": ["math", "string"] },
-        "565": { "topicTags": ["depth-first-search", "array"] },
-        "566": { "topicTags": ["array", "matrix", "simulation"] },
-        "567": { "topicTags": ["hash-table", "two-pointers", "string", "sliding-window"] },
-        "568": { "topicTags": ["array", "dynamic-programming", "matrix"] },
-        "569": { "topicTags": ["database"] },
-        "570": { "topicTags": ["database"] },
-        "571": { "topicTags": ["database"] },
-        "572": { "topicTags": ["tree", "depth-first-search", "binary-tree", "string-matching", "hash-function"] },
-        "573": { "topicTags": ["array", "math"] },
-        "574": { "topicTags": ["database"] },
-        "575": { "topicTags": ["array", "hash-table"] },
-        "576": { "topicTags": ["dynamic-programming"] },
-        "577": { "topicTags": ["database"] },
-        "578": { "topicTags": ["database"] },
-        "579": { "topicTags": ["database"] },
-        "580": { "topicTags": ["database"] },
-        "581": { "topicTags": ["stack", "greedy", "array", "two-pointers", "sorting", "monotonic-stack"] },
-        "582": { "topicTags": ["tree", "depth-first-search", "breadth-first-search", "array", "hash-table"] },
-        "583": { "topicTags": ["string", "dynamic-programming"] },
-        "584": { "topicTags": ["database"] },
-        "585": { "topicTags": ["database"] },
-        "586": { "topicTags": ["database"] },
-        "587": { "topicTags": ["geometry", "array", "math"] },
-        "588": { "topicTags": ["design", "trie", "hash-table", "string"] },
-        "589": { "topicTags": ["stack", "tree", "depth-first-search"] },
-        "590": { "topicTags": ["stack", "tree", "depth-first-search"] },
-        "591": { "topicTags": ["stack", "string"] },
-        "592": { "topicTags": ["math", "string", "simulation"] },
-        "593": { "topicTags": ["geometry", "math"] },
-        "594": { "topicTags": ["array", "hash-table", "sorting"] },
-        "595": { "topicTags": ["database"] },
-        "596": { "topicTags": ["database"] },
-        "597": { "topicTags": ["database"] },
-        "598": { "topicTags": ["array", "math"] },
-        "599": { "topicTags": ["array", "hash-table", "string"] },
-        "600": { "topicTags": ["dynamic-programming"] },
-        "601": { "topicTags": ["database"] },
-        "602": { "topicTags": ["database"] },
-        "603": { "topicTags": ["database"] },
-        "604": { "topicTags": ["design", "array", "hash-table", "string", "iterator"] },
-        "605": { "topicTags": ["greedy", "array"] },
-        "606": { "topicTags": ["tree", "depth-first-search", "string", "binary-tree"] },
-        "607": { "topicTags": ["database"] },
-        "608": { "topicTags": ["database"] },
-        "609": { "topicTags": ["array", "hash-table", "string"] },
-        "610": { "topicTags": ["database"] },
-        "611": { "topicTags": ["greedy", "array", "two-pointers", "binary-search", "sorting"] },
-        "612": { "topicTags": ["database"] },
-        "613": { "topicTags": ["database"] },
-        "614": { "topicTags": ["database"] },
-        "615": { "topicTags": ["database"] },
-        "616": { "topicTags": ["trie", "array", "hash-table", "string", "string-matching"] },
-        "617": { "topicTags": ["tree", "depth-first-search", "breadth-first-search", "binary-tree"] },
-        "618": { "topicTags": ["database"] },
-        "619": { "topicTags": ["database"] },
-        "620": { "topicTags": ["database"] },
-        "621": { "topicTags": ["greedy", "array", "hash-table", "counting", "sorting", "heap-priority-queue"] },
-        "622": { "topicTags": ["design", "queue", "array", "linked-list"] },
-        "623": { "topicTags": ["tree", "depth-first-search", "breadth-first-search", "binary-tree"] },
-        "624": { "topicTags": ["greedy", "array"] },
-        "625": { "topicTags": ["greedy", "math"] },
-        "626": { "topicTags": ["database"] },
-        "627": { "topicTags": ["database"] },
-        "628": { "topicTags": ["array", "math", "sorting"] },
-        "629": { "topicTags": ["dynamic-programming"] },
-        "630": { "topicTags": ["greedy", "array", "heap-priority-queue"] },
-        "631": { "topicTags": ["graph", "design", "topological-sort"] },
-        "632": { "topicTags": ["greedy", "array", "hash-table", "sorting", "sliding-window", "heap-priority-queue"] },
-        "633": { "topicTags": ["math", "two-pointers", "binary-search"] },
-        "634": { "topicTags": ["math", "dynamic-programming"] },
-        "635": { "topicTags": ["design", "hash-table", "string", "ordered-set"] },
-        "636": { "topicTags": ["stack", "array"] },
-        "637": { "topicTags": ["tree", "depth-first-search", "breadth-first-search", "binary-tree"] },
-        "638": { "topicTags": ["bit-manipulation", "memoization", "array", "dynamic-programming", "backtracking", "bitmask"] },
-        "639": { "topicTags": ["string", "dynamic-programming"] },
-        "640": { "topicTags": ["math", "string", "simulation"] },
-        "641": { "topicTags": ["design", "queue", "array", "linked-list"] },
-        "642": { "topicTags": ["design", "trie", "string", "data-stream"] },
-        "643": { "topicTags": ["array", "sliding-window"] },
-        "644": { "topicTags": ["array", "binary-search", "prefix-sum"] },
-        "645": { "topicTags": ["bit-manipulation", "array", "hash-table", "sorting"] },
-        "646": { "topicTags": ["greedy", "array", "dynamic-programming", "sorting"] },
-        "647": { "topicTags": ["string", "dynamic-programming"] },
-        "648": { "topicTags": ["trie", "array", "hash-table", "string"] },
-        "649": { "topicTags": ["greedy", "queue", "string"] },
-        "650": { "topicTags": ["math", "dynamic-programming"] },
-        "651": { "topicTags": ["math", "dynamic-programming"] },
-        "652": { "topicTags": ["tree", "depth-first-search", "hash-table", "binary-tree"] },
-        "653": { "topicTags": ["tree", "depth-first-search", "breadth-first-search", "binary-search-tree", "hash-table", "two-pointers", "binary-tree"] },
-        "654": { "topicTags": ["stack", "tree", "array", "divide-and-conquer", "binary-tree", "monotonic-stack"] },
-        "655": { "topicTags": ["tree", "depth-first-search", "breadth-first-search", "binary-tree"] },
-        "656": { "topicTags": ["array", "dynamic-programming"] },
-        "657": { "topicTags": ["string", "simulation"] },
-        "658": { "topicTags": ["array", "two-pointers", "binary-search", "sorting", "heap-priority-queue"] },
-        "659": { "topicTags": ["greedy", "array", "hash-table", "heap-priority-queue"] },
-        "660": { "topicTags": ["math"] },
-        "661": { "topicTags": ["array", "matrix"] },
-        "662": { "topicTags": ["tree", "depth-first-search", "breadth-first-search", "binary-tree"] },
-        "663": { "topicTags": ["tree", "depth-first-search", "binary-tree"] },
-        "664": { "topicTags": ["string", "dynamic-programming"] },
-        "665": { "topicTags": ["array"] },
-        "666": { "topicTags": ["tree", "depth-first-search", "array", "binary-tree"] },
-        "667": { "topicTags": ["array", "math"] },
-        "668": { "topicTags": ["math", "binary-search"] },
-        "669": { "topicTags": ["tree", "depth-first-search", "binary-search-tree", "binary-tree"] },
-        "670": { "topicTags": ["greedy", "math"] },
-        "671": { "topicTags": ["tree", "depth-first-search", "binary-tree"] },
-        "672": { "topicTags": ["bit-manipulation", "depth-first-search", "breadth-first-search", "math"] },
-        "673": { "topicTags": ["binary-indexed-tree", "segment-tree", "array", "dynamic-programming"] },
-        "674": { "topicTags": ["array"] },
-        "675": { "topicTags": ["breadth-first-search", "array", "matrix", "heap-priority-queue"] },
-        "676": { "topicTags": ["design", "trie", "hash-table", "string"] },
-        "677": { "topicTags": ["design", "trie", "hash-table", "string"] },
-        "678": { "topicTags": ["stack", "greedy", "string", "dynamic-programming"] },
-        "679": { "topicTags": ["array", "math", "backtracking"] },
-        "680": { "topicTags": ["greedy", "two-pointers", "string"] },
-        "681": { "topicTags": ["string", "enumeration"] },
-        "682": { "topicTags": ["stack", "array", "simulation"] },
-        "683": { "topicTags": ["binary-indexed-tree", "array", "ordered-set", "sliding-window"] },
-        "684": { "topicTags": ["depth-first-search", "breadth-first-search", "union-find", "graph"] },
-        "685": { "topicTags": ["depth-first-search", "breadth-first-search", "union-find", "graph"] },
-        "686": { "topicTags": ["string", "string-matching"] },
-        "687": { "topicTags": ["tree", "depth-first-search", "binary-tree"] },
-        "688": { "topicTags": ["dynamic-programming"] },
-        "689": { "topicTags": ["array", "dynamic-programming"] },
-        "690": { "topicTags": ["depth-first-search", "breadth-first-search", "hash-table"] },
-        "691": { "topicTags": ["bit-manipulation", "array", "string", "dynamic-programming", "backtracking", "bitmask"] },
-        "692": { "topicTags": ["trie", "hash-table", "string", "bucket-sort", "counting", "sorting", "heap-priority-queue"] },
-        "693": { "topicTags": ["bit-manipulation"] },
-        "694": { "topicTags": ["depth-first-search", "breadth-first-search", "union-find", "hash-table", "hash-function"] },
-        "695": { "topicTags": ["depth-first-search", "breadth-first-search", "union-find", "array", "matrix"] },
-        "696": { "topicTags": ["two-pointers", "string"] },
-        "697": { "topicTags": ["array", "hash-table"] },
-        "698": { "topicTags": ["bit-manipulation", "memoization", "array", "dynamic-programming", "backtracking", "bitmask"] },
-        "699": { "topicTags": ["segment-tree", "array", "ordered-set"] },
-        "700": { "topicTags": ["tree", "binary-search-tree", "binary-tree"] },
-        "701": { "topicTags": ["tree", "binary-search-tree", "binary-tree"] },
-        "702": { "topicTags": ["array", "binary-search", "interactive"] },
-        "703": { "topicTags": ["tree", "design", "binary-search-tree", "binary-tree", "data-stream", "heap-priority-queue"] },
-        "704": { "topicTags": ["array", "binary-search"] },
-        "705": { "topicTags": ["design", "array", "hash-table", "linked-list", "hash-function"] },
-        "706": { "topicTags": ["design", "array", "hash-table", "linked-list", "hash-function"] },
-        "707": { "topicTags": ["design", "linked-list"] },
-        "708": { "topicTags": ["linked-list"] },
-        "709": { "topicTags": ["string"] },
-        "710": { "topicTags": ["hash-table", "math", "binary-search", "sorting", "randomized"] },
-        "711": { "topicTags": ["depth-first-search", "breadth-first-search", "union-find", "hash-table", "hash-function"] },
-        "712": { "topicTags": ["string", "dynamic-programming"] },
-        "713": { "topicTags": ["array", "sliding-window"] },
-        "714": { "topicTags": ["greedy", "array", "dynamic-programming"] },
-        "715": { "topicTags": ["design", "segment-tree", "ordered-set"] },
-        "716": { "topicTags": ["stack", "design", "linked-list", "doubly-linked-list", "ordered-set"] },
-        "717": { "topicTags": ["array"] },
-        "718": { "topicTags": ["array", "binary-search", "dynamic-programming", "sliding-window", "hash-function", "rolling-hash"] },
-        "719": { "topicTags": ["array", "two-pointers", "binary-search", "sorting"] },
-        "720": { "topicTags": ["trie", "array", "hash-table", "string", "sorting"] },
-        "721": { "topicTags": ["depth-first-search", "breadth-first-search", "union-find", "array", "string"] },
-        "722": { "topicTags": ["array", "string"] },
-        "723": { "topicTags": ["array", "two-pointers", "matrix", "simulation"] },
-        "724": { "topicTags": ["array", "prefix-sum"] },
-        "725": { "topicTags": ["linked-list"] },
-        "726": { "topicTags": ["stack", "hash-table", "string", "sorting"] },
-        "727": { "topicTags": ["string", "dynamic-programming", "sliding-window"] },
-        "728": { "topicTags": ["math"] },
-        "729": { "topicTags": ["design", "segment-tree", "binary-search", "ordered-set"] },
-        "730": { "topicTags": ["string", "dynamic-programming"] },
-        "731": { "topicTags": ["design", "segment-tree", "binary-search", "ordered-set"] },
-        "732": { "topicTags": ["design", "segment-tree", "binary-search", "ordered-set"] },
-        "733": { "topicTags": ["depth-first-search", "breadth-first-search", "array", "matrix"] },
-        "734": { "topicTags": ["array", "hash-table", "string"] },
-        "735": { "topicTags": ["stack", "array"] },
-        "736": { "topicTags": ["stack", "recursion", "hash-table", "string"] },
-        "737": { "topicTags": ["depth-first-search", "breadth-first-search", "union-find", "array", "hash-table", "string"] },
-        "738": { "topicTags": ["greedy", "math"] },
-        "739": { "topicTags": ["stack", "array", "monotonic-stack"] },
-        "740": { "topicTags": ["array", "hash-table", "dynamic-programming"] },
-        "741": { "topicTags": ["array", "dynamic-programming", "matrix"] },
-        "742": { "topicTags": ["tree", "depth-first-search", "breadth-first-search", "binary-tree"] },
-        "743": { "topicTags": ["depth-first-search", "breadth-first-search", "graph", "shortest-path", "heap-priority-queue"] },
-        "744": { "topicTags": ["array", "binary-search"] },
-        "745": { "topicTags": ["design", "trie", "hash-table", "string"] },
-        "746": { "topicTags": ["array", "dynamic-programming"] },
-        "747": { "topicTags": ["array", "sorting"] },
-        "748": { "topicTags": ["array", "hash-table", "string"] },
-        "749": { "topicTags": ["depth-first-search", "breadth-first-search", "array", "matrix", "simulation"] },
-        "750": { "topicTags": ["array", "math", "dynamic-programming", "matrix"] },
-        "751": { "topicTags": ["bit-manipulation", "string"] },
-        "752": { "topicTags": ["breadth-first-search", "array", "hash-table", "string"] },
-        "753": { "topicTags": ["depth-first-search", "graph", "eulerian-circuit"] },
-        "754": { "topicTags": ["math", "binary-search"] },
-        "755": { "topicTags": ["array", "simulation"] },
-        "756": { "topicTags": ["bit-manipulation", "depth-first-search", "breadth-first-search"] },
-        "757": { "topicTags": ["greedy", "array", "sorting"] },
-        "758": { "topicTags": ["trie", "array", "hash-table", "string", "string-matching"] },
-        "759": { "topicTags": ["array", "sorting", "heap-priority-queue"] },
-        "760": { "topicTags": ["array", "hash-table"] },
-        "761": { "topicTags": ["recursion", "string"] },
-        "762": { "topicTags": ["bit-manipulation", "math"] },
-        "763": { "topicTags": ["greedy", "hash-table", "two-pointers", "string"] },
-        "764": { "topicTags": ["array", "dynamic-programming"] },
-        "765": { "topicTags": ["greedy", "depth-first-search", "breadth-first-search", "union-find", "graph"] },
-        "766": { "topicTags": ["array", "matrix"] },
-        "767": { "topicTags": ["greedy", "hash-table", "string", "counting", "sorting", "heap-priority-queue"] },
-        "768": { "topicTags": ["stack", "greedy", "array", "sorting", "monotonic-stack"] },
-        "769": { "topicTags": ["stack", "greedy", "array", "sorting", "monotonic-stack"] },
-        "770": { "topicTags": ["stack", "recursion", "hash-table", "math", "string"] },
-        "771": { "topicTags": ["hash-table", "string"] },
-        "772": { "topicTags": ["stack", "recursion", "math", "string"] },
-        "773": { "topicTags": ["breadth-first-search", "array", "matrix"] },
-        "774": { "topicTags": ["array", "binary-search"] },
-        "775": { "topicTags": ["array", "math"] },
-        "776": { "topicTags": ["tree", "binary-search-tree", "recursion", "binary-tree"] },
-        "777": { "topicTags": ["two-pointers", "string"] },
-        "778": { "topicTags": ["depth-first-search", "breadth-first-search", "union-find", "array", "binary-search", "matrix", "heap-priority-queue"] },
-        "779": { "topicTags": ["bit-manipulation", "recursion", "math"] },
-        "780": { "topicTags": ["math"] },
-        "781": { "topicTags": ["greedy", "array", "hash-table", "math"] },
-        "782": { "topicTags": ["bit-manipulation", "array", "math", "matrix"] },
-        "783": { "topicTags": ["tree", "depth-first-search", "breadth-first-search", "binary-search-tree", "binary-tree"] },
-        "784": { "topicTags": ["bit-manipulation", "string", "backtracking"] },
-        "785": { "topicTags": ["depth-first-search", "breadth-first-search", "union-find", "graph"] },
-        "786": { "topicTags": ["array", "binary-search", "sorting", "heap-priority-queue"] },
-        "787": { "topicTags": ["depth-first-search", "breadth-first-search", "graph", "dynamic-programming", "shortest-path", "heap-priority-queue"] },
-        "788": { "topicTags": ["math", "dynamic-programming"] },
-        "789": { "topicTags": ["array", "math"] },
-        "790": { "topicTags": ["dynamic-programming"] },
-        "791": { "topicTags": ["hash-table", "string", "sorting"] },
-        "792": { "topicTags": ["trie", "hash-table", "string", "sorting"] },
-        "793": { "topicTags": ["math", "binary-search"] },
-        "794": { "topicTags": ["array", "string"] },
-        "795": { "topicTags": ["array", "two-pointers"] },
-        "796": { "topicTags": ["string", "string-matching"] },
-        "797": { "topicTags": ["depth-first-search", "breadth-first-search", "graph", "backtracking"] },
-        "798": { "topicTags": ["array", "prefix-sum"] },
-        "799": { "topicTags": ["dynamic-programming"] },
-        "800": { "topicTags": ["math", "string", "enumeration"] },
-        "801": { "topicTags": ["array", "dynamic-programming"] },
-        "802": { "topicTags": ["depth-first-search", "breadth-first-search", "graph", "topological-sort"] },
-        "803": { "topicTags": ["union-find", "array", "matrix"] },
-        "804": { "topicTags": ["array", "hash-table", "string"] },
-        "805": { "topicTags": ["bit-manipulation", "array", "math", "dynamic-programming", "bitmask"] },
-        "806": { "topicTags": ["array", "string"] },
-        "807": { "topicTags": ["greedy", "array", "matrix"] },
-        "808": { "topicTags": ["math", "dynamic-programming", "probability-and-statistics"] },
-        "809": { "topicTags": ["array", "two-pointers", "string"] },
-        "810": { "topicTags": ["bit-manipulation", "brainteaser", "array", "math", "game-theory"] },
-        "811": { "topicTags": ["array", "hash-table", "string", "counting"] },
-        "812": { "topicTags": ["geometry", "array", "math"] },
-        "813": { "topicTags": ["array", "dynamic-programming"] },
-        "814": { "topicTags": ["tree", "depth-first-search", "binary-tree"] },
-        "815": { "topicTags": ["breadth-first-search", "array", "hash-table"] },
-        "816": { "topicTags": ["string", "backtracking"] },
-        "817": { "topicTags": ["array", "hash-table", "linked-list"] },
-        "818": { "topicTags": ["dynamic-programming"] },
-        "819": { "topicTags": ["hash-table", "string", "counting"] },
-        "820": { "topicTags": ["trie", "array", "hash-table", "string"] },
-        "821": { "topicTags": ["array", "two-pointers", "string"] },
-        "822": { "topicTags": ["array", "hash-table"] },
-        "823": { "topicTags": ["array", "hash-table", "dynamic-programming"] },
-        "824": { "topicTags": ["string"] },
-        "825": { "topicTags": ["array", "two-pointers", "binary-search", "sorting"] },
-        "826": { "topicTags": ["greedy", "array", "two-pointers", "binary-search", "sorting"] },
-        "827": { "topicTags": ["depth-first-search", "breadth-first-search", "union-find", "array", "matrix"] },
-        "828": { "topicTags": ["hash-table", "string", "dynamic-programming"] },
-        "829": { "topicTags": ["math", "enumeration"] },
-        "830": { "topicTags": ["string"] },
-        "831": { "topicTags": ["string"] },
-        "832": { "topicTags": ["array", "two-pointers", "matrix", "simulation"] },
-        "833": { "topicTags": ["array", "string", "sorting"] },
-        "834": { "topicTags": ["tree", "depth-first-search", "graph", "dynamic-programming"] },
-        "835": { "topicTags": ["array", "matrix"] },
-        "836": { "topicTags": ["geometry", "math"] },
-        "837": { "topicTags": ["math", "dynamic-programming", "sliding-window", "probability-and-statistics"] },
-        "838": { "topicTags": ["two-pointers", "string", "dynamic-programming"] },
-        "839": { "topicTags": ["depth-first-search", "breadth-first-search", "union-find", "array", "string"] },
-        "840": { "topicTags": ["array", "math", "matrix"] },
-        "841": { "topicTags": ["depth-first-search", "breadth-first-search", "graph"] },
-        "842": { "topicTags": ["string", "backtracking"] },
-        "843": { "topicTags": ["array", "math", "string", "game-theory", "interactive"] },
-        "844": { "topicTags": ["stack", "two-pointers", "string", "simulation"] },
-        "845": { "topicTags": ["array", "two-pointers", "dynamic-programming", "enumeration"] },
-        "846": { "topicTags": ["greedy", "array", "hash-table", "sorting"] },
-        "847": { "topicTags": ["bit-manipulation", "breadth-first-search", "graph", "dynamic-programming", "bitmask"] },
-        "848": { "topicTags": ["array", "string"] },
-        "849": { "topicTags": ["array"] },
-        "850": { "topicTags": ["segment-tree", "array", "ordered-set", "line-sweep"] },
-        "851": { "topicTags": ["depth-first-search", "graph", "topological-sort", "array"] },
-        "852": { "topicTags": ["array", "binary-search"] },
-        "853": { "topicTags": ["stack", "array", "sorting", "monotonic-stack"] },
-        "854": { "topicTags": ["breadth-first-search", "string"] },
-        "855": { "topicTags": ["design", "ordered-set"] },
-        "856": { "topicTags": ["stack", "string"] },
-        "857": { "topicTags": ["greedy", "array", "sorting", "heap-priority-queue"] },
-        "858": { "topicTags": ["geometry", "math"] },
-        "859": { "topicTags": ["hash-table", "string"] },
-        "860": { "topicTags": ["greedy", "array"] },
-        "861": { "topicTags": ["greedy", "bit-manipulation", "array", "matrix"] },
-        "862": { "topicTags": ["queue", "array", "binary-search", "prefix-sum", "sliding-window", "monotonic-queue", "heap-priority-queue"] },
-        "863": { "topicTags": ["tree", "depth-first-search", "breadth-first-search", "binary-tree"] },
-        "864": { "topicTags": ["bit-manipulation", "breadth-first-search"] },
-        "865": { "topicTags": ["tree", "depth-first-search", "breadth-first-search", "hash-table", "binary-tree"] },
-        "866": { "topicTags": ["math"] },
-        "867": { "topicTags": ["array", "matrix", "simulation"] },
-        "868": { "topicTags": ["bit-manipulation"] },
-        "869": { "topicTags": ["math", "counting", "enumeration", "sorting"] },
-        "870": { "topicTags": ["greedy", "array", "two-pointers", "sorting"] },
-        "871": { "topicTags": ["greedy", "array", "dynamic-programming", "heap-priority-queue"] },
-        "872": { "topicTags": ["tree", "depth-first-search", "binary-tree"] },
-        "873": { "topicTags": ["array", "hash-table", "dynamic-programming"] },
-        "874": { "topicTags": ["array", "simulation"] },
-        "875": { "topicTags": ["array", "binary-search"] },
-        "876": { "topicTags": ["linked-list", "two-pointers"] },
-        "877": { "topicTags": ["array", "math", "dynamic-programming", "game-theory"] },
-        "878": { "topicTags": ["math", "binary-search"] },
-        "879": { "topicTags": ["array", "dynamic-programming"] },
-        "880": { "topicTags": ["stack", "string"] },
-        "881": { "topicTags": ["greedy", "array", "two-pointers", "sorting"] },
-        "882": { "topicTags": ["graph", "shortest-path", "heap-priority-queue"] },
-        "883": { "topicTags": ["geometry", "array", "math", "matrix"] },
-        "884": { "topicTags": ["hash-table", "string"] },
-        "885": { "topicTags": ["array", "matrix", "simulation"] },
-        "886": { "topicTags": ["depth-first-search", "breadth-first-search", "union-find", "graph"] },
-        "887": { "topicTags": ["math", "binary-search", "dynamic-programming"] },
-        "888": { "topicTags": ["array", "hash-table", "binary-search", "sorting"] },
-        "889": { "topicTags": ["tree", "array", "hash-table", "divide-and-conquer", "binary-tree"] },
-        "890": { "topicTags": ["array", "hash-table", "string"] },
-        "891": { "topicTags": ["array", "math", "sorting"] },
-        "892": { "topicTags": ["geometry", "array", "math", "matrix"] },
-        "893": { "topicTags": ["array", "hash-table", "string"] },
-        "894": { "topicTags": ["tree", "recursion", "memoization", "dynamic-programming", "binary-tree"] },
-        "895": { "topicTags": ["stack", "design", "hash-table", "ordered-set"] },
-        "896": { "topicTags": ["array"] },
-        "897": { "topicTags": ["stack", "tree", "depth-first-search", "binary-search-tree", "binary-tree"] },
-        "898": { "topicTags": ["bit-manipulation", "array", "dynamic-programming"] },
-        "899": { "topicTags": ["math", "string", "sorting"] },
-        "900": { "topicTags": ["design", "array", "counting", "iterator"] },
-        "901": { "topicTags": ["stack", "design", "data-stream", "monotonic-stack"] },
-        "902": { "topicTags": ["array", "math", "string", "binary-search", "dynamic-programming"] },
-        "903": { "topicTags": ["dynamic-programming"] },
-        "904": { "topicTags": ["array", "hash-table", "sliding-window"] },
-        "905": { "topicTags": ["array", "two-pointers", "sorting"] },
-        "906": { "topicTags": ["math", "enumeration"] },
-        "907": { "topicTags": ["stack", "array", "dynamic-programming", "monotonic-stack"] },
-        "908": { "topicTags": ["array", "math"] },
-        "909": { "topicTags": ["breadth-first-search", "array", "matrix"] },
-        "910": { "topicTags": ["greedy", "array", "math", "sorting"] },
-        "911": { "topicTags": ["design", "array", "hash-table", "binary-search"] },
-        "912": { "topicTags": ["array", "divide-and-conquer", "bucket-sort", "counting-sort", "radix-sort", "sorting", "heap-priority-queue", "merge-sort"] },
-        "913": { "topicTags": ["graph", "topological-sort", "memoization", "math", "dynamic-programming", "game-theory"] },
-        "914": { "topicTags": ["array", "hash-table", "math", "counting", "number-theory"] },
-        "915": { "topicTags": ["array"] },
-        "916": { "topicTags": ["array", "hash-table", "string"] },
-        "917": { "topicTags": ["two-pointers", "string"] },
-        "918": { "topicTags": ["queue", "array", "divide-and-conquer", "dynamic-programming", "monotonic-queue"] },
-        "919": { "topicTags": ["tree", "breadth-first-search", "design", "binary-tree"] },
-        "920": { "topicTags": ["math", "dynamic-programming", "combinatorics"] },
-        "921": { "topicTags": ["stack", "greedy", "string"] },
-        "922": { "topicTags": ["array", "two-pointers", "sorting"] },
-        "923": { "topicTags": ["array", "hash-table", "two-pointers", "counting", "sorting"] },
-        "924": { "topicTags": ["depth-first-search", "breadth-first-search", "union-find", "array", "matrix"] },
-        "925": { "topicTags": ["two-pointers", "string"] },
-        "926": { "topicTags": ["string", "dynamic-programming"] },
-        "927": { "topicTags": ["array", "math"] },
-        "928": { "topicTags": ["depth-first-search", "breadth-first-search", "union-find", "array", "matrix"] },
-        "929": { "topicTags": ["array", "hash-table", "string"] },
-        "930": { "topicTags": ["array", "hash-table", "prefix-sum", "sliding-window"] },
-        "931": { "topicTags": ["array", "dynamic-programming", "matrix"] },
-        "932": { "topicTags": ["array", "math", "divide-and-conquer"] },
-        "933": { "topicTags": ["design", "queue", "data-stream"] },
-        "934": { "topicTags": ["depth-first-search", "breadth-first-search", "array", "matrix"] },
-        "935": { "topicTags": ["dynamic-programming"] },
-        "936": { "topicTags": ["stack", "greedy", "queue", "string"] },
-        "937": { "topicTags": ["array", "string", "sorting"] },
-        "938": { "topicTags": ["tree", "depth-first-search", "binary-search-tree", "binary-tree"] },
-        "939": { "topicTags": ["geometry", "array", "hash-table", "math", "sorting"] },
-        "940": { "topicTags": ["string", "dynamic-programming"] },
-        "941": { "topicTags": ["array"] },
-        "942": { "topicTags": ["greedy", "array", "two-pointers", "string"] },
-        "943": { "topicTags": ["bit-manipulation", "array", "string", "dynamic-programming", "bitmask"] },
-        "944": { "topicTags": ["array", "string"] },
-        "945": { "topicTags": ["greedy", "array", "counting", "sorting"] },
-        "946": { "topicTags": ["stack", "array", "simulation"] },
-        "947": { "topicTags": ["depth-first-search", "union-find", "graph"] },
-        "948": { "topicTags": ["greedy", "array", "two-pointers", "sorting"] },
-        "949": { "topicTags": ["string", "enumeration"] },
-        "950": { "topicTags": ["queue", "array", "sorting", "simulation"] },
-        "951": { "topicTags": ["tree", "depth-first-search", "binary-tree"] },
-        "952": { "topicTags": ["union-find", "array", "math"] },
-        "953": { "topicTags": ["array", "hash-table", "string"] },
-        "954": { "topicTags": ["greedy", "array", "hash-table", "sorting"] },
-        "955": { "topicTags": ["greedy", "array", "string"] },
-        "956": { "topicTags": ["array", "dynamic-programming"] },
-        "957": { "topicTags": ["bit-manipulation", "array", "hash-table", "math"] },
-        "958": { "topicTags": ["tree", "breadth-first-search", "binary-tree"] },
-        "959": { "topicTags": ["depth-first-search", "breadth-first-search", "union-find", "graph"] },
-        "960": { "topicTags": ["array", "string", "dynamic-programming"] },
-        "961": { "topicTags": ["array", "hash-table"] },
-        "962": { "topicTags": ["stack", "array", "monotonic-stack"] },
-        "963": { "topicTags": ["geometry", "array", "math"] },
-        "964": { "topicTags": ["math", "dynamic-programming"] },
-        "965": { "topicTags": ["tree", "depth-first-search", "breadth-first-search", "binary-tree"] },
-        "966": { "topicTags": ["array", "hash-table", "string"] },
-        "967": { "topicTags": ["breadth-first-search", "backtracking"] },
-        "968": { "topicTags": ["tree", "depth-first-search", "dynamic-programming", "binary-tree"] },
-        "969": { "topicTags": ["greedy", "array", "two-pointers", "sorting"] },
-        "970": { "topicTags": ["hash-table", "math"] },
-        "971": { "topicTags": ["tree", "depth-first-search", "binary-tree"] },
-        "972": { "topicTags": ["math", "string"] },
-        "973": { "topicTags": ["geometry", "array", "math", "divide-and-conquer", "quickselect", "sorting", "heap-priority-queue"] },
-        "974": { "topicTags": ["array", "hash-table", "prefix-sum"] },
-        "975": { "topicTags": ["stack", "array", "dynamic-programming", "ordered-set", "monotonic-stack"] },
-        "976": { "topicTags": ["greedy", "array", "math", "sorting"] },
-        "977": { "topicTags": ["array", "two-pointers", "sorting"] },
-        "978": { "topicTags": ["array", "dynamic-programming", "sliding-window"] },
-        "979": { "topicTags": ["tree", "depth-first-search", "binary-tree"] },
-        "980": { "topicTags": ["bit-manipulation", "array", "backtracking", "matrix"] },
-        "981": { "topicTags": ["design", "hash-table", "string", "binary-search"] },
-        "982": { "topicTags": ["bit-manipulation", "array", "hash-table"] },
-        "983": { "topicTags": ["array", "dynamic-programming"] },
-        "984": { "topicTags": ["greedy", "string"] },
-        "985": { "topicTags": ["array", "simulation"] },
-        "986": { "topicTags": ["array", "two-pointers"] },
-        "987": { "topicTags": ["tree", "depth-first-search", "breadth-first-search", "hash-table", "binary-tree"] },
-        "988": { "topicTags": ["tree", "depth-first-search", "string", "binary-tree"] },
-        "989": { "topicTags": ["array", "math"] },
-        "990": { "topicTags": ["union-find", "graph", "array", "string"] },
-        "991": { "topicTags": ["greedy", "math"] },
-        "992": { "topicTags": ["array", "hash-table", "counting", "sliding-window"] },
-        "993": { "topicTags": ["tree", "depth-first-search", "breadth-first-search", "binary-tree"] },
-        "994": { "topicTags": ["breadth-first-search", "array", "matrix"] },
-        "995": { "topicTags": ["bit-manipulation", "queue", "array", "prefix-sum", "sliding-window"] },
-        "996": { "topicTags": ["bit-manipulation", "array", "math", "dynamic-programming", "backtracking", "bitmask"] },
-        "997": { "topicTags": ["graph", "array", "hash-table"] },
-        "998": { "topicTags": ["tree", "binary-tree"] },
-        "999": { "topicTags": ["array", "matrix", "simulation"] },
-        "1000": { "topicTags": ["array", "dynamic-programming"] },
-        "1001": { "topicTags": ["array", "hash-table"] },
-        "1002": { "topicTags": ["array", "hash-table", "string"] },
-        "1003": { "topicTags": ["stack", "string"] },
-        "1004": { "topicTags": ["array", "binary-search", "prefix-sum", "sliding-window"] },
-        "1005": { "topicTags": ["greedy", "array", "sorting"] },
-        "1006": { "topicTags": ["stack", "math", "simulation"] },
-        "1007": { "topicTags": ["greedy", "array"] },
-        "1008": { "topicTags": ["stack", "tree", "binary-search-tree", "array", "binary-tree", "monotonic-stack"] },
-        "1009": { "topicTags": ["bit-manipulation"] },
-        "1010": { "topicTags": ["array", "hash-table", "counting"] },
-        "1011": { "topicTags": ["array", "binary-search"] },
-        "1012": { "topicTags": ["math", "dynamic-programming"] },
-        "1013": { "topicTags": ["greedy", "array"] },
-        "1014": { "topicTags": ["array", "dynamic-programming"] },
-        "1015": { "topicTags": ["hash-table", "math"] },
-        "1016": { "topicTags": ["string"] },
-        "1017": { "topicTags": ["math"] },
-        "1018": { "topicTags": ["array"] },
-        "1019": { "topicTags": ["stack", "array", "linked-list", "monotonic-stack"] },
-        "1020": { "topicTags": ["depth-first-search", "breadth-first-search", "union-find", "array", "matrix"] },
-        "1021": { "topicTags": ["stack", "string"] },
-        "1022": { "topicTags": ["tree", "depth-first-search", "binary-tree"] },
-        "1023": { "topicTags": ["trie", "two-pointers", "string", "string-matching"] },
-        "1024": { "topicTags": ["greedy", "array", "dynamic-programming"] },
-        "1025": { "topicTags": ["brainteaser", "math", "dynamic-programming", "game-theory"] },
-        "1026": { "topicTags": ["tree", "depth-first-search", "binary-tree"] },
-        "1027": { "topicTags": ["array", "hash-table", "binary-search", "dynamic-programming"] },
-        "1028": { "topicTags": ["tree", "depth-first-search", "string", "binary-tree"] },
-        "1029": { "topicTags": ["greedy", "array", "sorting"] },
-        "1030": { "topicTags": ["geometry", "array", "math", "matrix", "sorting"] },
-        "1031": { "topicTags": ["array", "dynamic-programming", "sliding-window"] },
-        "1032": { "topicTags": ["design", "trie", "array", "string", "data-stream"] },
-        "1033": { "topicTags": ["brainteaser", "math"] },
-        "1034": { "topicTags": ["depth-first-search", "breadth-first-search", "array", "matrix"] },
-        "1035": { "topicTags": ["array", "dynamic-programming"] },
-        "1036": { "topicTags": ["depth-first-search", "breadth-first-search", "array", "hash-table"] },
-        "1037": { "topicTags": ["geometry", "array", "math"] },
-        "1038": { "topicTags": ["tree", "depth-first-search", "binary-search-tree", "binary-tree"] },
-        "1039": { "topicTags": ["array", "dynamic-programming"] },
-        "1040": { "topicTags": ["array", "math", "two-pointers", "sorting"] },
-        "1041": { "topicTags": ["math", "string", "simulation"] },
-        "1042": { "topicTags": ["depth-first-search", "breadth-first-search", "graph"] },
-        "1043": { "topicTags": ["array", "dynamic-programming"] },
-        "1044": { "topicTags": ["string", "binary-search", "suffix-array", "sliding-window", "hash-function", "rolling-hash"] },
-        "1045": { "topicTags": ["database"] },
-        "1046": { "topicTags": ["array", "heap-priority-queue"] },
-        "1047": { "topicTags": ["stack", "string"] },
-        "1048": { "topicTags": ["array", "hash-table", "two-pointers", "string", "dynamic-programming"] },
-        "1049": { "topicTags": ["array", "dynamic-programming"] },
-        "1050": { "topicTags": ["database"] },
-        "1051": { "topicTags": ["array", "counting-sort", "sorting"] },
-        "1052": { "topicTags": ["array", "sliding-window"] },
-        "1053": { "topicTags": ["greedy", "array"] },
-        "1054": { "topicTags": ["greedy", "array", "hash-table", "counting", "sorting", "heap-priority-queue"] },
-        "1055": { "topicTags": ["greedy", "string", "dynamic-programming"] },
-        "1056": { "topicTags": ["math"] },
-        "1057": { "topicTags": ["greedy", "array", "sorting"] },
-        "1058": { "topicTags": ["greedy", "array", "math", "string"] },
-        "1059": { "topicTags": ["depth-first-search", "graph"] },
-        "1060": { "topicTags": ["array", "binary-search"] },
-        "1061": { "topicTags": ["union-find", "string"] },
-        "1062": { "topicTags": ["string", "binary-search", "dynamic-programming", "suffix-array", "hash-function", "rolling-hash"] },
-        "1063": { "topicTags": ["stack", "array", "monotonic-stack"] },
-        "1064": { "topicTags": ["array", "binary-search"] },
-        "1065": { "topicTags": ["trie", "array", "string", "sorting"] },
-        "1066": { "topicTags": ["bit-manipulation", "array", "dynamic-programming", "backtracking", "bitmask"] },
-        "1067": { "topicTags": ["math", "dynamic-programming"] },
-        "1068": { "topicTags": ["database"] },
-        "1069": { "topicTags": ["database"] },
-        "1070": { "topicTags": ["database"] },
-        "1071": { "topicTags": ["math", "string"] },
-        "1072": { "topicTags": ["array", "hash-table", "matrix"] },
-        "1073": { "topicTags": ["array", "math"] },
-        "1074": { "topicTags": ["array", "hash-table", "matrix", "prefix-sum"] },
-        "1075": { "topicTags": ["database"] },
-        "1076": { "topicTags": ["database"] },
-        "1077": { "topicTags": ["database"] },
-        "1078": { "topicTags": ["string"] },
-        "1079": { "topicTags": ["string", "backtracking"] },
-        "1080": { "topicTags": ["tree", "depth-first-search", "binary-tree"] },
-        "1081": { "topicTags": ["stack", "greedy", "string", "monotonic-stack"] },
-        "1082": { "topicTags": ["database"] },
-        "1083": { "topicTags": ["database"] },
-        "1084": { "topicTags": ["database"] },
-        "1085": { "topicTags": ["array", "math"] },
-        "1086": { "topicTags": ["array", "hash-table", "sorting"] },
-        "1087": { "topicTags": ["breadth-first-search", "string", "backtracking"] },
-        "1088": { "topicTags": ["math", "backtracking"] },
-        "1089": { "topicTags": ["array", "two-pointers"] },
-        "1090": { "topicTags": ["greedy", "array", "hash-table", "counting", "sorting"] },
-        "1091": { "topicTags": ["breadth-first-search", "array", "matrix"] },
-        "1092": { "topicTags": ["string", "dynamic-programming"] },
-        "1093": { "topicTags": ["math", "two-pointers", "probability-and-statistics"] },
-        "1094": { "topicTags": ["array", "prefix-sum", "sorting", "simulation", "heap-priority-queue"] },
-        "1095": { "topicTags": ["array", "binary-search", "interactive"] },
-        "1096": { "topicTags": ["stack", "breadth-first-search", "string", "backtracking"] },
-        "1097": { "topicTags": ["database"] },
-        "1098": { "topicTags": ["database"] },
-        "1099": { "topicTags": ["array", "two-pointers", "binary-search", "sorting"] },
-        "1100": { "topicTags": ["hash-table", "string", "sliding-window"] },
-        "1101": { "topicTags": ["union-find", "array"] },
-        "1102": { "topicTags": ["depth-first-search", "breadth-first-search", "union-find", "array", "matrix", "heap-priority-queue"] },
-        "1103": { "topicTags": ["math", "simulation"] },
-        "1104": { "topicTags": ["tree", "math", "binary-tree"] },
-        "1105": { "topicTags": ["array", "dynamic-programming"] },
-        "1106": { "topicTags": ["stack", "recursion", "string"] },
-        "1107": { "topicTags": ["database"] },
-        "1108": { "topicTags": ["string"] },
-        "1109": { "topicTags": ["array", "prefix-sum"] },
-        "1110": { "topicTags": ["tree", "depth-first-search", "binary-tree"] },
-        "1111": { "topicTags": ["stack", "string"] },
-        "1112": { "topicTags": ["database"] },
-        "1113": { "topicTags": ["database"] },
-        "1114": { "topicTags": ["concurrency"] },
-        "1115": { "topicTags": ["concurrency"] },
-        "1116": { "topicTags": ["concurrency"] },
-        "1117": { "topicTags": ["concurrency"] },
-        "1118": { "topicTags": ["math"] },
-        "1119": { "topicTags": ["string"] },
-        "1120": { "topicTags": ["tree", "depth-first-search", "binary-tree"] },
-        "1121": { "topicTags": ["greedy", "array"] },
-        "1122": { "topicTags": ["array", "hash-table", "counting-sort", "sorting"] },
-        "1123": { "topicTags": ["tree", "depth-first-search", "breadth-first-search", "hash-table", "binary-tree"] },
-        "1124": { "topicTags": ["stack", "array", "hash-table", "prefix-sum", "monotonic-stack"] },
-        "1125": { "topicTags": ["bit-manipulation", "array", "dynamic-programming", "bitmask"] },
-        "1126": { "topicTags": ["database"] },
-        "1127": { "topicTags": ["database"] },
-        "1128": { "topicTags": ["array", "hash-table", "counting"] },
-        "1129": { "topicTags": ["breadth-first-search", "graph"] },
-        "1130": { "topicTags": ["stack", "greedy", "dynamic-programming", "monotonic-stack"] },
-        "1131": { "topicTags": ["array", "math"] },
-        "1132": { "topicTags": ["database"] },
-        "1133": { "topicTags": ["array", "hash-table", "sorting"] },
-        "1134": { "topicTags": ["math"] },
-        "1135": { "topicTags": ["union-find", "graph", "minimum-spanning-tree", "heap-priority-queue"] },
-        "1136": { "topicTags": ["graph", "topological-sort"] },
-        "1137": { "topicTags": ["memoization", "math", "dynamic-programming"] },
-        "1138": { "topicTags": ["hash-table", "string"] },
-        "1139": { "topicTags": ["array", "dynamic-programming", "matrix"] },
-        "1140": { "topicTags": ["array", "math", "dynamic-programming", "game-theory"] },
-        "1141": { "topicTags": ["database"] },
-        "1142": { "topicTags": ["database"] },
-        "1143": { "topicTags": ["string", "dynamic-programming"] },
-        "1144": { "topicTags": ["greedy", "array"] },
-        "1145": { "topicTags": ["tree", "depth-first-search", "binary-tree"] },
-        "1146": { "topicTags": ["design", "array", "hash-table", "binary-search"] },
-        "1147": { "topicTags": ["greedy", "two-pointers", "string", "dynamic-programming", "hash-function", "rolling-hash"] },
-        "1148": { "topicTags": ["database"] },
-        "1149": { "topicTags": ["database"] },
-        "1150": { "topicTags": ["array", "binary-search"] },
-        "1151": { "topicTags": ["array", "sliding-window"] },
-        "1152": { "topicTags": ["array", "hash-table", "sorting"] },
-        "1153": { "topicTags": ["hash-table", "string"] },
-        "1154": { "topicTags": ["math", "string"] },
-        "1155": { "topicTags": ["dynamic-programming"] },
-        "1156": { "topicTags": ["string", "sliding-window"] },
-        "1157": { "topicTags": ["design", "binary-indexed-tree", "segment-tree", "array", "binary-search"] },
-        "1158": { "topicTags": ["database"] },
-        "1159": { "topicTags": ["database"] },
-        "1160": { "topicTags": ["array", "hash-table", "string"] },
-        "1161": { "topicTags": ["tree", "depth-first-search", "breadth-first-search", "binary-tree"] },
-        "1162": { "topicTags": ["breadth-first-search", "array", "dynamic-programming", "matrix"] },
-        "1163": { "topicTags": ["two-pointers", "string"] },
-        "1164": { "topicTags": ["database"] },
-        "1165": { "topicTags": ["hash-table", "string"] },
-        "1166": { "topicTags": ["design", "trie", "hash-table", "string"] },
-        "1167": { "topicTags": ["greedy", "array", "heap-priority-queue"] },
-        "1168": { "topicTags": ["union-find", "graph", "minimum-spanning-tree"] },
-        "1169": { "topicTags": ["array", "hash-table", "string", "sorting"] },
-        "1170": { "topicTags": ["array", "hash-table", "string", "binary-search", "sorting"] },
-        "1171": { "topicTags": ["hash-table", "linked-list"] },
-        "1172": { "topicTags": ["stack", "design", "hash-table", "heap-priority-queue"] },
-        "1173": { "topicTags": ["database"] },
-        "1174": { "topicTags": ["database"] },
-        "1175": { "topicTags": ["math"] },
-        "1176": { "topicTags": ["array", "sliding-window"] },
-        "1177": { "topicTags": ["bit-manipulation", "hash-table", "string", "prefix-sum"] },
-        "1178": { "topicTags": ["bit-manipulation", "trie", "array", "hash-table", "string"] },
-        "1179": { "topicTags": ["database"] },
-        "1180": { "topicTags": ["math", "string"] },
-        "1181": { "topicTags": ["array", "hash-table", "string", "sorting"] },
-        "1182": { "topicTags": ["array", "binary-search", "dynamic-programming"] },
-        "1183": { "topicTags": ["greedy", "heap-priority-queue"] },
-        "1184": { "topicTags": ["array"] },
-        "1185": { "topicTags": ["math"] },
-        "1186": { "topicTags": ["array", "dynamic-programming"] },
-        "1187": { "topicTags": ["array", "binary-search", "dynamic-programming"] },
-        "1188": { "topicTags": ["concurrency"] },
-        "1189": { "topicTags": ["hash-table", "string", "counting"] },
-        "1190": { "topicTags": ["stack", "string"] },
-        "1191": { "topicTags": ["array", "dynamic-programming"] },
-        "1192": { "topicTags": ["depth-first-search", "graph", "biconnected-component"] },
-        "1193": { "topicTags": ["database"] },
-        "1194": { "topicTags": ["database"] },
-        "1195": { "topicTags": ["concurrency"] },
-        "1196": { "topicTags": ["greedy", "array", "sorting"] },
-        "1197": { "topicTags": ["breadth-first-search"] },
-        "1198": { "topicTags": ["array", "hash-table", "binary-search", "counting", "matrix"] },
-        "1199": { "topicTags": ["greedy", "math", "heap-priority-queue"] },
-        "1200": { "topicTags": ["array", "sorting"] },
-        "1201": { "topicTags": ["math", "binary-search", "number-theory"] },
-        "1202": { "topicTags": ["depth-first-search", "breadth-first-search", "union-find", "hash-table", "string"] },
-        "1203": { "topicTags": ["depth-first-search", "breadth-first-search", "graph", "topological-sort"] },
-        "1204": { "topicTags": ["database"] },
-        "1205": { "topicTags": ["database"] },
-        "1206": { "topicTags": ["design", "linked-list"] },
-        "1207": { "topicTags": ["array", "hash-table"] },
-        "1208": { "topicTags": ["string", "binary-search", "prefix-sum", "sliding-window"] },
-        "1209": { "topicTags": ["stack", "string"] },
-        "1210": { "topicTags": ["breadth-first-search", "array", "matrix"] },
-        "1211": { "topicTags": ["database"] },
-        "1212": { "topicTags": ["database"] },
-        "1213": { "topicTags": ["array", "hash-table", "binary-search", "counting"] },
-        "1214": { "topicTags": ["stack", "tree", "depth-first-search", "binary-search-tree", "two-pointers", "binary-search", "binary-tree"] },
-        "1215": { "topicTags": ["breadth-first-search", "backtracking"] },
-        "1216": { "topicTags": ["string", "dynamic-programming"] },
-        "1217": { "topicTags": ["greedy", "array", "math"] },
-        "1218": { "topicTags": ["array", "hash-table", "dynamic-programming"] },
-        "1219": { "topicTags": ["array", "backtracking", "matrix"] },
-        "1220": { "topicTags": ["dynamic-programming"] },
-        "1221": { "topicTags": ["greedy", "string", "counting"] },
-        "1222": { "topicTags": ["array", "matrix", "simulation"] },
-        "1223": { "topicTags": ["array", "dynamic-programming"] },
-        "1224": { "topicTags": ["array", "hash-table"] },
-        "1225": { "topicTags": ["database"] },
-        "1226": { "topicTags": ["concurrency"] },
-        "1227": { "topicTags": ["brainteaser", "math", "dynamic-programming", "probability-and-statistics"] },
-        "1228": { "topicTags": ["array", "math"] },
-        "1229": { "topicTags": ["array", "two-pointers", "sorting"] },
-        "1230": { "topicTags": ["math", "dynamic-programming", "probability-and-statistics"] },
-        "1231": { "topicTags": ["array", "binary-search"] },
-        "1232": { "topicTags": ["geometry", "array", "math"] },
-        "1233": { "topicTags": ["trie", "array", "string"] },
-        "1234": { "topicTags": ["string", "sliding-window"] },
-        "1235": { "topicTags": ["array", "binary-search", "dynamic-programming", "sorting"] },
-        "1236": { "topicTags": ["depth-first-search", "breadth-first-search", "string", "interactive"] },
-        "1237": { "topicTags": ["math", "two-pointers", "binary-search", "interactive"] },
-        "1238": { "topicTags": ["bit-manipulation", "math", "backtracking"] },
-        "1239": { "topicTags": ["bit-manipulation", "array", "string", "backtracking"] },
-        "1240": { "topicTags": ["dynamic-programming", "backtracking"] },
-        "1241": { "topicTags": ["database"] },
-        "1242": { "topicTags": ["depth-first-search", "breadth-first-search", "concurrency"] },
-        "1243": { "topicTags": ["array", "simulation"] },
-        "1244": { "topicTags": ["design", "hash-table", "sorting"] },
-        "1245": { "topicTags": ["tree", "depth-first-search", "breadth-first-search", "graph", "topological-sort"] },
-        "1246": { "topicTags": ["array", "dynamic-programming"] },
-        "1247": { "topicTags": ["greedy", "math", "string"] },
-        "1248": { "topicTags": ["array", "hash-table", "math", "sliding-window"] },
-        "1249": { "topicTags": ["stack", "string"] },
-        "1250": { "topicTags": ["array", "math", "number-theory"] },
-        "1251": { "topicTags": ["database"] },
-        "1252": { "topicTags": ["array", "math", "simulation"] },
-        "1253": { "topicTags": ["greedy", "array", "matrix"] },
-        "1254": { "topicTags": ["depth-first-search", "breadth-first-search", "union-find", "array", "matrix"] },
-        "1255": { "topicTags": ["bit-manipulation", "array", "string", "dynamic-programming", "backtracking", "bitmask"] },
-        "1256": { "topicTags": ["bit-manipulation", "math", "string"] },
-        "1257": { "topicTags": ["tree", "depth-first-search", "breadth-first-search", "array", "hash-table", "string"] },
-        "1258": { "topicTags": ["union-find", "array", "hash-table", "string", "backtracking"] },
-        "1259": { "topicTags": ["math", "dynamic-programming"] },
-        "1260": { "topicTags": ["array", "matrix", "simulation"] },
-        "1261": { "topicTags": ["tree", "depth-first-search", "breadth-first-search", "design", "hash-table", "binary-tree"] },
-        "1262": { "topicTags": ["greedy", "array", "dynamic-programming"] },
-        "1263": { "topicTags": ["breadth-first-search", "array", "matrix", "heap-priority-queue"] },
-        "1264": { "topicTags": ["database"] },
-        "1265": { "topicTags": ["stack", "recursion", "linked-list", "two-pointers"] },
-        "1266": { "topicTags": ["geometry", "array", "math"] },
-        "1267": { "topicTags": ["depth-first-search", "breadth-first-search", "union-find", "array", "counting", "matrix"] },
-        "1268": { "topicTags": ["trie", "array", "string"] },
-        "1269": { "topicTags": ["dynamic-programming"] },
-        "1270": { "topicTags": ["database"] },
-        "1271": { "topicTags": ["math", "string"] },
-        "1272": { "topicTags": ["array"] },
-        "1273": { "topicTags": ["tree", "depth-first-search", "breadth-first-search"] },
-        "1274": { "topicTags": ["array", "divide-and-conquer", "interactive"] },
-        "1275": { "topicTags": ["array", "hash-table", "matrix", "simulation"] },
-        "1276": { "topicTags": ["math"] },
-        "1277": { "topicTags": ["array", "dynamic-programming", "matrix"] },
-        "1278": { "topicTags": ["string", "dynamic-programming"] },
-        "1279": { "topicTags": ["concurrency"] },
-        "1280": { "topicTags": ["database"] },
-        "1281": { "topicTags": ["math"] },
-        "1282": { "topicTags": ["array", "hash-table"] },
-        "1283": { "topicTags": ["array", "binary-search"] },
-        "1284": { "topicTags": ["bit-manipulation", "breadth-first-search", "array", "matrix"] },
-        "1285": { "topicTags": ["database"] },
-        "1286": { "topicTags": ["design", "string", "backtracking", "iterator"] },
-        "1287": { "topicTags": ["array"] },
-        "1288": { "topicTags": ["array", "sorting"] },
-        "1289": { "topicTags": ["array", "dynamic-programming", "matrix"] },
-        "1290": { "topicTags": ["linked-list", "math"] },
-        "1291": { "topicTags": ["enumeration"] },
-        "1292": { "topicTags": ["array", "binary-search", "matrix", "prefix-sum"] },
-        "1293": { "topicTags": ["breadth-first-search", "array", "matrix"] },
-        "1294": { "topicTags": ["database"] },
-        "1295": { "topicTags": ["array"] },
-        "1296": { "topicTags": ["greedy", "array", "hash-table", "sorting"] },
-        "1297": { "topicTags": ["hash-table", "string", "sliding-window"] },
-        "1298": { "topicTags": ["breadth-first-search", "array"] },
-        "1299": { "topicTags": ["array"] },
-        "1300": { "topicTags": ["array", "binary-search", "sorting"] },
-        "1301": { "topicTags": ["array", "dynamic-programming", "matrix"] },
-        "1302": { "topicTags": ["tree", "depth-first-search", "breadth-first-search", "binary-tree"] },
-        "1303": { "topicTags": ["database"] },
-        "1304": { "topicTags": ["array", "math"] },
-        "1305": { "topicTags": ["tree", "depth-first-search", "binary-search-tree", "binary-tree", "sorting"] },
-        "1306": { "topicTags": ["depth-first-search", "breadth-first-search", "array"] },
-        "1307": { "topicTags": ["array", "math", "string", "backtracking"] },
-        "1308": { "topicTags": ["database"] },
-        "1309": { "topicTags": ["string"] },
-        "1310": { "topicTags": ["bit-manipulation", "array", "prefix-sum"] },
-        "1311": { "topicTags": ["breadth-first-search", "array", "hash-table", "sorting"] },
-        "1312": { "topicTags": ["string", "dynamic-programming"] },
-        "1313": { "topicTags": ["array"] },
-        "1314": { "topicTags": ["array", "matrix", "prefix-sum"] },
-        "1315": { "topicTags": ["tree", "depth-first-search", "breadth-first-search", "binary-tree"] },
-        "1316": { "topicTags": ["trie", "string", "hash-function", "rolling-hash"] },
-        "1317": { "topicTags": ["math"] },
-        "1318": { "topicTags": ["bit-manipulation"] },
-        "1319": { "topicTags": ["depth-first-search", "breadth-first-search", "union-find", "graph"] },
-        "1320": { "topicTags": ["string", "dynamic-programming"] },
-        "1321": { "topicTags": ["database"] },
-        "1322": { "topicTags": ["database"] },
-        "1323": { "topicTags": ["greedy", "math"] },
-        "1324": { "topicTags": ["array", "string", "simulation"] },
-        "1325": { "topicTags": ["tree", "depth-first-search", "binary-tree"] },
-        "1326": { "topicTags": ["greedy", "array", "dynamic-programming"] },
-        "1327": { "topicTags": ["database"] },
-        "1328": { "topicTags": ["greedy", "string"] },
-        "1329": { "topicTags": ["array", "matrix", "sorting"] },
-        "1330": { "topicTags": ["greedy", "array", "math"] },
-        "1331": { "topicTags": ["array", "hash-table", "sorting"] },
-        "1332": { "topicTags": ["two-pointers", "string"] },
-        "1333": { "topicTags": ["array", "sorting"] },
-        "1334": { "topicTags": ["graph", "dynamic-programming", "shortest-path"] },
-        "1335": { "topicTags": ["array", "dynamic-programming"] },
-        "1336": { "topicTags": ["database"] },
-        "1337": { "topicTags": ["array", "binary-search", "matrix", "sorting", "heap-priority-queue"] },
-        "1338": { "topicTags": ["greedy", "array", "hash-table", "sorting", "heap-priority-queue"] },
-        "1339": { "topicTags": ["tree", "depth-first-search", "binary-tree"] },
-        "1340": { "topicTags": ["array", "dynamic-programming", "sorting"] },
-        "1341": { "topicTags": ["database"] },
-        "1342": { "topicTags": ["bit-manipulation", "math"] },
-        "1343": { "topicTags": ["array", "sliding-window"] },
-        "1344": { "topicTags": ["math"] },
-        "1345": { "topicTags": ["breadth-first-search", "array", "hash-table"] },
-        "1346": { "topicTags": ["array", "hash-table", "two-pointers", "binary-search", "sorting"] },
-        "1347": { "topicTags": ["hash-table", "string", "counting"] },
-        "1348": { "topicTags": ["design", "hash-table", "binary-search", "ordered-set", "sorting"] },
-        "1349": { "topicTags": ["bit-manipulation", "array", "dynamic-programming", "bitmask", "matrix"] },
-        "1350": { "topicTags": ["database"] },
-        "1351": { "topicTags": ["array", "binary-search", "matrix"] },
-        "1352": { "topicTags": ["design", "queue", "array", "math", "data-stream"] },
-        "1353": { "topicTags": ["greedy", "array", "heap-priority-queue"] },
-        "1354": { "topicTags": ["array", "heap-priority-queue"] },
-        "1355": { "topicTags": ["database"] },
-        "1356": { "topicTags": ["bit-manipulation", "array", "counting", "sorting"] },
-        "1357": { "topicTags": ["design", "array", "hash-table"] },
-        "1358": { "topicTags": ["hash-table", "string", "sliding-window"] },
-        "1359": { "topicTags": ["math", "dynamic-programming", "combinatorics"] },
-        "1360": { "topicTags": ["math", "string"] },
-        "1361": { "topicTags": ["tree", "depth-first-search", "breadth-first-search", "union-find", "graph", "binary-tree"] },
-        "1362": { "topicTags": ["math"] },
-        "1363": { "topicTags": ["greedy", "array", "dynamic-programming"] },
-        "1364": { "topicTags": ["database"] },
-        "1365": { "topicTags": ["array", "hash-table", "counting", "sorting"] },
-        "1366": { "topicTags": ["array", "hash-table", "string", "counting", "sorting"] },
-        "1367": { "topicTags": ["tree", "depth-first-search", "breadth-first-search", "linked-list", "binary-tree"] },
-        "1368": { "topicTags": ["breadth-first-search", "graph", "array", "matrix", "shortest-path", "heap-priority-queue"] },
-        "1369": { "topicTags": ["database"] },
-        "1370": { "topicTags": ["hash-table", "string", "counting"] },
-        "1371": { "topicTags": ["bit-manipulation", "hash-table", "string", "prefix-sum"] },
-        "1372": { "topicTags": ["tree", "depth-first-search", "dynamic-programming", "binary-tree"] },
-        "1373": { "topicTags": ["tree", "depth-first-search", "binary-search-tree", "dynamic-programming", "binary-tree"] },
-        "1374": { "topicTags": ["string"] },
-        "1375": { "topicTags": ["array"] },
-        "1376": { "topicTags": ["tree", "depth-first-search", "breadth-first-search"] },
-        "1377": { "topicTags": ["tree", "depth-first-search", "breadth-first-search", "graph"] },
-        "1378": { "topicTags": ["database"] },
-        "1379": { "topicTags": ["tree", "depth-first-search", "breadth-first-search", "binary-tree"] },
-        "1380": { "topicTags": ["array", "matrix"] },
-        "1381": { "topicTags": ["stack", "design", "array"] },
-        "1382": { "topicTags": ["greedy", "tree", "depth-first-search", "binary-search-tree", "divide-and-conquer", "binary-tree"] },
-        "1383": { "topicTags": ["greedy", "array", "sorting", "heap-priority-queue"] },
-        "1384": { "topicTags": ["database"] },
-        "1385": { "topicTags": ["array", "two-pointers", "binary-search", "sorting"] },
-        "1386": { "topicTags": ["greedy", "bit-manipulation", "array", "hash-table"] },
-        "1387": { "topicTags": ["memoization", "dynamic-programming", "sorting"] },
-        "1388": { "topicTags": ["greedy", "array", "dynamic-programming", "heap-priority-queue"] },
-        "1389": { "topicTags": ["array", "simulation"] },
-        "1390": { "topicTags": ["array", "math"] },
-        "1391": { "topicTags": ["depth-first-search", "breadth-first-search", "union-find", "array", "matrix"] },
-        "1392": { "topicTags": ["string", "string-matching", "hash-function", "rolling-hash"] },
-        "1393": { "topicTags": ["database"] },
-        "1394": { "topicTags": ["array", "hash-table", "counting"] },
-        "1395": { "topicTags": ["binary-indexed-tree", "array", "dynamic-programming"] },
-        "1396": { "topicTags": ["design", "hash-table", "string"] },
-        "1397": { "topicTags": ["string", "dynamic-programming", "string-matching"] },
-        "1398": { "topicTags": ["database"] },
-        "1399": { "topicTags": ["hash-table", "math"] },
-        "1400": { "topicTags": ["greedy", "hash-table", "string", "counting"] },
-        "1401": { "topicTags": ["geometry", "math"] },
-        "1402": { "topicTags": ["greedy", "array", "dynamic-programming", "sorting"] },
-        "1403": { "topicTags": ["greedy", "array", "sorting"] },
-        "1404": { "topicTags": ["bit-manipulation", "string"] },
-        "1405": { "topicTags": ["greedy", "string", "heap-priority-queue"] },
-        "1406": { "topicTags": ["array", "math", "dynamic-programming", "game-theory"] },
-        "1407": { "topicTags": ["database"] },
-        "1408": { "topicTags": ["string", "string-matching"] },
-        "1409": { "topicTags": ["binary-indexed-tree", "array", "simulation"] },
-        "1410": { "topicTags": ["hash-table", "string"] },
-        "1411": { "topicTags": ["dynamic-programming"] },
-        "1412": { "topicTags": ["database"] },
-        "1413": { "topicTags": ["array", "prefix-sum"] },
-        "1414": { "topicTags": ["greedy"] },
-        "1415": { "topicTags": ["string", "backtracking"] },
-        "1416": { "topicTags": ["string", "dynamic-programming"] },
-        "1417": { "topicTags": ["string"] },
-        "1418": { "topicTags": ["array", "hash-table", "string", "ordered-set", "sorting"] },
-        "1419": { "topicTags": ["string", "counting"] },
-        "1420": { "topicTags": ["dynamic-programming"] },
-        "1421": { "topicTags": ["database"] },
-        "1422": { "topicTags": ["string"] },
-        "1423": { "topicTags": ["array", "prefix-sum", "sliding-window"] },
-        "1424": { "topicTags": ["array", "sorting", "heap-priority-queue"] },
-        "1425": { "topicTags": ["queue", "array", "dynamic-programming", "sliding-window", "monotonic-queue", "heap-priority-queue"] },
-        "1426": { "topicTags": ["array", "hash-table"] },
-        "1427": { "topicTags": ["array", "math", "string"] },
-        "1428": { "topicTags": ["array", "binary-search", "interactive", "matrix"] },
-        "1429": { "topicTags": ["design", "queue", "array", "hash-table", "data-stream"] },
-        "1430": { "topicTags": ["tree", "depth-first-search", "breadth-first-search", "binary-tree"] },
-        "1431": { "topicTags": ["array"] },
-        "1432": { "topicTags": ["greedy", "math"] },
-        "1433": { "topicTags": ["greedy", "string", "sorting"] },
-        "1434": { "topicTags": ["bit-manipulation", "array", "dynamic-programming", "bitmask"] },
-        "1435": { "topicTags": ["database"] },
-        "1436": { "topicTags": ["hash-table", "string"] },
-        "1437": { "topicTags": ["array"] },
-        "1438": { "topicTags": ["queue", "array", "ordered-set", "sliding-window", "monotonic-queue", "heap-priority-queue"] },
-        "1439": { "topicTags": ["array", "binary-search", "matrix", "heap-priority-queue"] },
-        "1440": { "topicTags": ["database"] },
-        "1441": { "topicTags": ["stack", "array", "simulation"] },
-        "1442": { "topicTags": ["bit-manipulation", "array", "hash-table", "math", "prefix-sum"] },
-        "1443": { "topicTags": ["tree", "depth-first-search", "breadth-first-search", "hash-table"] },
-        "1444": { "topicTags": ["memoization", "array", "dynamic-programming", "matrix"] },
-        "1445": { "topicTags": ["database"] },
-        "1446": { "topicTags": ["string"] },
-        "1447": { "topicTags": ["math", "string", "number-theory"] },
-        "1448": { "topicTags": ["tree", "depth-first-search", "breadth-first-search", "binary-tree"] },
-        "1449": { "topicTags": ["array", "dynamic-programming"] },
-        "1450": { "topicTags": ["array"] },
-        "1451": { "topicTags": ["string", "sorting"] },
-        "1452": { "topicTags": ["array", "hash-table", "string"] },
-        "1453": { "topicTags": ["geometry", "array", "math"] },
-        "1454": { "topicTags": ["database"] },
-        "1455": { "topicTags": ["string", "string-matching"] },
-        "1456": { "topicTags": ["string", "sliding-window"] },
-        "1457": { "topicTags": ["bit-manipulation", "tree", "depth-first-search", "breadth-first-search", "binary-tree"] },
-        "1458": { "topicTags": ["array", "dynamic-programming"] },
-        "1459": { "topicTags": ["database"] },
-        "1460": { "topicTags": ["array", "hash-table", "sorting"] },
-        "1461": { "topicTags": ["bit-manipulation", "hash-table", "string", "hash-function", "rolling-hash"] },
-        "1462": { "topicTags": ["depth-first-search", "breadth-first-search", "graph", "topological-sort"] },
-        "1463": { "topicTags": ["array", "dynamic-programming", "matrix"] },
-        "1464": { "topicTags": ["array", "sorting", "heap-priority-queue"] },
-        "1465": { "topicTags": ["greedy", "array", "sorting"] },
-        "1466": { "topicTags": ["depth-first-search", "breadth-first-search", "graph"] },
-        "1467": { "topicTags": ["math", "dynamic-programming", "backtracking", "combinatorics", "probability-and-statistics"] },
-        "1468": { "topicTags": ["database"] },
-        "1469": { "topicTags": ["tree", "depth-first-search", "breadth-first-search", "binary-tree"] },
-        "1470": { "topicTags": ["array"] },
-        "1471": { "topicTags": ["array", "two-pointers", "sorting"] },
-        "1472": { "topicTags": ["stack", "design", "array", "linked-list", "data-stream", "doubly-linked-list"] },
-        "1473": { "topicTags": ["array", "dynamic-programming"] },
-        "1474": { "topicTags": ["linked-list"] },
-        "1475": { "topicTags": ["stack", "array", "monotonic-stack"] },
-        "1476": { "topicTags": ["design", "array", "matrix"] },
-        "1477": { "topicTags": ["array", "hash-table", "binary-search", "dynamic-programming", "sliding-window"] },
-        "1478": { "topicTags": ["array", "math", "dynamic-programming", "sorting"] },
-        "1479": { "topicTags": ["database"] },
-        "1480": { "topicTags": ["array", "prefix-sum"] },
-        "1481": { "topicTags": ["greedy", "array", "hash-table", "counting", "sorting"] },
-        "1482": { "topicTags": ["array", "binary-search"] },
-        "1483": { "topicTags": ["tree", "depth-first-search", "breadth-first-search", "design", "binary-search", "dynamic-programming"] },
-        "1484": { "topicTags": ["database"] },
-        "1485": { "topicTags": ["tree", "depth-first-search", "breadth-first-search", "hash-table", "binary-tree"] },
-        "1486": { "topicTags": ["bit-manipulation", "math"] },
-        "1487": { "topicTags": ["array", "hash-table", "string"] },
-        "1488": { "topicTags": ["greedy", "array", "hash-table", "binary-search", "heap-priority-queue"] },
-        "1489": { "topicTags": ["union-find", "graph", "minimum-spanning-tree", "sorting", "strongly-connected-component"] },
-        "1490": { "topicTags": ["tree", "depth-first-search", "breadth-first-search", "hash-table"] },
-        "1491": { "topicTags": ["array", "sorting"] },
-        "1492": { "topicTags": ["math"] },
-        "1493": { "topicTags": ["array", "dynamic-programming", "sliding-window"] },
-        "1494": { "topicTags": ["bit-manipulation", "graph", "dynamic-programming", "bitmask"] },
-        "1495": { "topicTags": ["database"] },
-        "1496": { "topicTags": ["hash-table", "string"] },
-        "1497": { "topicTags": ["array", "hash-table", "counting"] },
-        "1498": { "topicTags": ["array", "two-pointers", "binary-search", "sorting"] },
-        "1499": { "topicTags": ["queue", "array", "sliding-window", "monotonic-queue", "heap-priority-queue"] },
-        "1500": { "topicTags": ["design", "hash-table", "data-stream", "heap-priority-queue"] },
-        "1501": { "topicTags": ["database"] },
-        "1502": { "topicTags": ["array", "sorting"] },
-        "1503": { "topicTags": ["brainteaser", "array", "simulation"] },
-        "1504": { "topicTags": ["stack", "array", "dynamic-programming", "matrix", "monotonic-stack"] },
-        "1505": { "topicTags": ["greedy", "binary-indexed-tree", "segment-tree", "string"] },
-        "1506": { "topicTags": ["bit-manipulation", "tree", "depth-first-search", "hash-table"] },
-        "1507": { "topicTags": ["string"] },
-        "1508": { "topicTags": ["array", "two-pointers", "binary-search", "sorting"] },
-        "1509": { "topicTags": ["greedy", "array", "sorting"] },
-        "1510": { "topicTags": ["math", "dynamic-programming", "game-theory"] },
-        "1511": { "topicTags": ["database"] },
-        "1512": { "topicTags": ["array", "hash-table", "math", "counting"] },
-        "1513": { "topicTags": ["math", "string"] },
-        "1514": { "topicTags": ["graph", "shortest-path", "heap-priority-queue"] },
-        "1515": { "topicTags": ["geometry", "math", "randomized"] },
-        "1516": { "topicTags": ["tree", "depth-first-search"] },
-        "1517": { "topicTags": ["database"] },
-        "1518": { "topicTags": ["math", "simulation"] },
-        "1519": { "topicTags": ["tree", "depth-first-search", "breadth-first-search", "hash-table", "counting"] },
-        "1520": { "topicTags": ["greedy", "string"] },
-        "1521": { "topicTags": ["bit-manipulation", "segment-tree", "array", "binary-search"] },
-        "1522": { "topicTags": ["tree", "depth-first-search"] },
-        "1523": { "topicTags": ["math"] },
-        "1524": { "topicTags": ["array", "math", "dynamic-programming", "prefix-sum"] },
-        "1525": { "topicTags": ["bit-manipulation", "string", "dynamic-programming"] },
-        "1526": { "topicTags": ["stack", "greedy", "array", "dynamic-programming", "monotonic-stack"] },
-        "1527": { "topicTags": ["database"] },
-        "1528": { "topicTags": ["array", "string"] },
-        "1529": { "topicTags": ["greedy", "string"] },
-        "1530": { "topicTags": ["tree", "depth-first-search", "binary-tree"] },
-        "1531": { "topicTags": ["string", "dynamic-programming"] },
-        "1532": { "topicTags": ["database"] },
-        "1533": { "topicTags": ["array", "binary-search", "interactive"] },
-        "1534": { "topicTags": ["array", "enumeration"] },
-        "1535": { "topicTags": ["array", "simulation"] },
-        "1536": { "topicTags": ["greedy", "array", "matrix"] },
-        "1537": { "topicTags": ["greedy", "array", "two-pointers", "dynamic-programming"] },
-        "1538": { "topicTags": ["array", "math", "interactive"] },
-        "1539": { "topicTags": ["array", "binary-search"] },
-        "1540": { "topicTags": ["hash-table", "string"] },
-        "1541": { "topicTags": ["stack", "greedy", "string"] },
-        "1542": { "topicTags": ["bit-manipulation", "hash-table", "string"] },
-        "1543": { "topicTags": ["database"] },
-        "1544": { "topicTags": ["stack", "string"] },
-        "1545": { "topicTags": ["recursion", "string"] },
-        "1546": { "topicTags": ["greedy", "array", "hash-table", "prefix-sum"] },
-        "1547": { "topicTags": ["array", "dynamic-programming"] },
-        "1548": { "topicTags": ["graph", "dynamic-programming"] },
-        "1549": { "topicTags": ["database"] },
-        "1550": { "topicTags": ["array"] },
-        "1551": { "topicTags": ["math"] },
-        "1552": { "topicTags": ["array", "binary-search", "sorting"] },
-        "1553": { "topicTags": ["memoization", "dynamic-programming"] },
-        "1554": { "topicTags": ["hash-table", "string", "hash-function", "rolling-hash"] },
-        "1555": { "topicTags": ["database"] },
-        "1556": { "topicTags": ["string"] },
-        "1557": { "topicTags": ["graph"] },
-        "1558": { "topicTags": ["greedy", "array"] },
-        "1559": { "topicTags": ["depth-first-search", "breadth-first-search", "union-find", "array", "matrix"] },
-        "1560": { "topicTags": ["array", "simulation"] },
-        "1561": { "topicTags": ["greedy", "array", "math", "game-theory", "sorting"] },
-        "1562": { "topicTags": ["array", "binary-search", "simulation"] },
-        "1563": { "topicTags": ["array", "math", "dynamic-programming", "game-theory"] },
-        "1564": { "topicTags": ["greedy", "array", "sorting"] },
-        "1565": { "topicTags": ["database"] },
-        "1566": { "topicTags": ["array", "enumeration"] },
-        "1567": { "topicTags": ["greedy", "array", "dynamic-programming"] },
-        "1568": { "topicTags": ["depth-first-search", "breadth-first-search", "array", "matrix", "strongly-connected-component"] },
-        "1569": { "topicTags": ["tree", "union-find", "binary-search-tree", "memoization", "array", "math", "divide-and-conquer", "dynamic-programming", "binary-tree", "combinatorics"] },
-        "1570": { "topicTags": ["design", "array", "hash-table", "two-pointers"] },
-        "1571": { "topicTags": ["database"] },
-        "1572": { "topicTags": ["array", "matrix"] },
-        "1573": { "topicTags": ["math", "string"] },
-        "1574": { "topicTags": ["stack", "array", "two-pointers", "binary-search", "monotonic-stack"] },
-        "1575": { "topicTags": ["memoization", "array", "dynamic-programming"] },
-        "1576": { "topicTags": ["string"] },
-        "1577": { "topicTags": ["array", "hash-table", "math", "two-pointers"] },
-        "1578": { "topicTags": ["greedy", "array", "string", "dynamic-programming"] },
-        "1579": { "topicTags": ["union-find", "graph"] },
-        "1580": { "topicTags": ["greedy", "array", "sorting"] },
-        "1581": { "topicTags": ["database"] },
-        "1582": { "topicTags": ["array", "matrix"] },
-        "1583": { "topicTags": ["array", "simulation"] },
-        "1584": { "topicTags": ["union-find", "array", "minimum-spanning-tree"] },
-        "1585": { "topicTags": ["greedy", "string", "sorting"] },
-        "1586": { "topicTags": ["stack", "tree", "design", "binary-search-tree", "binary-tree", "iterator"] },
-        "1587": { "topicTags": ["database"] },
-        "1588": { "topicTags": ["array", "math", "prefix-sum"] },
-        "1589": { "topicTags": ["greedy", "array", "prefix-sum", "sorting"] },
-        "1590": { "topicTags": ["array", "hash-table", "prefix-sum"] },
-        "1591": { "topicTags": ["graph", "topological-sort", "array", "matrix"] },
-        "1592": { "topicTags": ["string"] },
-        "1593": { "topicTags": ["hash-table", "string", "backtracking"] },
-        "1594": { "topicTags": ["array", "dynamic-programming", "matrix"] },
-        "1595": { "topicTags": ["bit-manipulation", "array", "dynamic-programming", "bitmask", "matrix"] },
-        "1596": { "topicTags": ["database"] },
-        "1597": { "topicTags": ["stack", "tree", "string", "binary-tree"] },
-        "1598": { "topicTags": ["stack", "array", "string"] },
-        "1599": { "topicTags": ["array", "simulation"] },
-        "1600": { "topicTags": ["tree", "depth-first-search", "design", "hash-table"] },
-        "1601": { "topicTags": ["bit-manipulation", "array", "backtracking", "enumeration"] },
-        "1602": { "topicTags": ["tree", "breadth-first-search", "binary-tree"] },
-        "1603": { "topicTags": ["design", "counting", "simulation"] },
-        "1604": { "topicTags": ["array", "hash-table", "string", "sorting"] },
-        "1605": { "topicTags": ["greedy", "array", "matrix"] },
-        "1606": { "topicTags": ["greedy", "array", "ordered-set", "heap-priority-queue"] },
-        "1607": { "topicTags": ["database"] },
-        "1608": { "topicTags": ["array", "binary-search", "sorting"] },
-        "1609": { "topicTags": ["tree", "breadth-first-search", "binary-tree"] },
-        "1610": { "topicTags": ["geometry", "array", "math", "sorting", "sliding-window"] },
-        "1611": { "topicTags": ["bit-manipulation", "memoization", "dynamic-programming"] },
-        "1612": { "topicTags": ["tree", "depth-first-search", "binary-tree"] },
-        "1613": { "topicTags": ["database"] },
-        "1614": { "topicTags": ["stack", "string"] },
-        "1615": { "topicTags": ["graph"] },
-        "1616": { "topicTags": ["two-pointers", "string"] },
-        "1617": { "topicTags": ["bit-manipulation", "tree", "dynamic-programming", "bitmask", "enumeration"] },
-        "1618": { "topicTags": ["array", "string", "binary-search", "interactive"] },
-        "1619": { "topicTags": ["array", "sorting"] },
-        "1620": { "topicTags": ["array", "enumeration"] },
-        "1621": { "topicTags": ["math", "dynamic-programming"] },
-        "1622": { "topicTags": ["design", "segment-tree", "math"] },
-        "1623": { "topicTags": ["database"] },
-        "1624": { "topicTags": ["hash-table", "string"] },
-        "1625": { "topicTags": ["breadth-first-search", "string"] },
-        "1626": { "topicTags": ["array", "dynamic-programming", "sorting"] },
-        "1627": { "topicTags": ["union-find", "array", "math"] },
-        "1628": { "topicTags": ["stack", "tree", "design", "math", "binary-tree"] },
-        "1629": { "topicTags": ["array", "string"] },
-        "1630": { "topicTags": ["array", "sorting"] },
-        "1631": { "topicTags": ["depth-first-search", "breadth-first-search", "union-find", "array", "binary-search", "matrix", "heap-priority-queue"] },
-        "1632": { "topicTags": ["greedy", "union-find", "graph", "topological-sort", "array", "matrix"] },
-        "1633": { "topicTags": ["database"] },
-        "1634": { "topicTags": ["linked-list", "math", "two-pointers"] },
-        "1635": { "topicTags": ["database"] },
-        "1636": { "topicTags": ["array", "hash-table", "sorting"] },
-        "1637": { "topicTags": ["array", "sorting"] },
-        "1638": { "topicTags": ["hash-table", "string", "dynamic-programming"] },
-        "1639": { "topicTags": ["array", "string", "dynamic-programming"] },
-        "1640": { "topicTags": ["array", "hash-table"] },
-        "1641": { "topicTags": ["dynamic-programming"] },
-        "1642": { "topicTags": ["greedy", "array", "heap-priority-queue"] },
-        "1643": { "topicTags": ["array", "math", "dynamic-programming", "combinatorics"] },
-        "1644": { "topicTags": ["tree", "depth-first-search", "binary-tree"] },
-        "1645": { "topicTags": ["database"] },
-        "1646": { "topicTags": ["array", "dynamic-programming", "simulation"] },
-        "1647": { "topicTags": ["greedy", "string", "sorting"] },
-        "1648": { "topicTags": ["greedy", "array", "math", "binary-search", "sorting", "heap-priority-queue"] },
-        "1649": { "topicTags": ["binary-indexed-tree", "segment-tree", "array", "binary-search", "divide-and-conquer", "ordered-set", "merge-sort"] },
-        "1650": { "topicTags": ["tree", "hash-table", "binary-tree"] },
-        "1651": { "topicTags": ["database"] },
-        "1652": { "topicTags": ["array"] },
-        "1653": { "topicTags": ["stack", "string", "dynamic-programming"] },
-        "1654": { "topicTags": ["breadth-first-search", "array", "dynamic-programming"] },
-        "1655": { "topicTags": ["bit-manipulation", "array", "dynamic-programming", "backtracking", "bitmask"] },
-        "1656": { "topicTags": ["design", "array", "hash-table", "data-stream"] },
-        "1657": { "topicTags": ["hash-table", "string", "sorting"] },
-        "1658": { "topicTags": ["array", "hash-table", "binary-search", "prefix-sum", "sliding-window"] },
-        "1659": { "topicTags": ["bit-manipulation", "memoization", "dynamic-programming", "bitmask"] },
-        "1660": { "topicTags": ["tree", "depth-first-search", "breadth-first-search", "hash-table", "binary-tree"] },
-        "1661": { "topicTags": ["database"] },
-        "1662": { "topicTags": ["array", "string"] },
-        "1663": { "topicTags": ["greedy", "string"] },
-        "1664": { "topicTags": ["array", "dynamic-programming"] },
-        "1665": { "topicTags": ["greedy", "array", "sorting"] },
-        "1666": { "topicTags": ["tree", "depth-first-search", "binary-tree"] },
-        "1667": { "topicTags": ["database"] },
-        "1668": { "topicTags": ["string", "string-matching"] },
-        "1669": { "topicTags": ["linked-list"] },
-        "1670": { "topicTags": ["design", "queue", "array", "linked-list", "data-stream"] },
-        "1671": { "topicTags": ["greedy", "array", "binary-search", "dynamic-programming"] },
-        "1672": { "topicTags": ["array", "matrix"] },
-        "1673": { "topicTags": ["stack", "greedy", "array", "monotonic-stack"] },
-        "1674": { "topicTags": ["array", "hash-table", "prefix-sum"] },
-        "1675": { "topicTags": ["greedy", "array", "ordered-set", "heap-priority-queue"] },
-        "1676": { "topicTags": ["tree", "depth-first-search", "binary-tree"] },
-        "1677": { "topicTags": ["database"] },
-        "1678": { "topicTags": ["string"] },
-        "1679": { "topicTags": ["array", "hash-table", "two-pointers", "sorting"] },
-        "1680": { "topicTags": ["bit-manipulation", "math", "simulation"] },
-        "1681": { "topicTags": ["bit-manipulation", "array", "dynamic-programming", "bitmask"] },
-        "1682": { "topicTags": ["string", "dynamic-programming"] },
-        "1683": { "topicTags": ["database"] },
-        "1684": { "topicTags": ["bit-manipulation", "array", "hash-table", "string"] },
-        "1685": { "topicTags": ["array", "math", "prefix-sum"] },
-        "1686": { "topicTags": ["greedy", "array", "math", "game-theory", "sorting", "heap-priority-queue"] },
-        "1687": { "topicTags": ["segment-tree", "queue", "array", "dynamic-programming", "monotonic-queue", "heap-priority-queue"] },
-        "1688": { "topicTags": ["math", "simulation"] },
-        "1689": { "topicTags": ["greedy", "string"] },
-        "1690": { "topicTags": ["array", "math", "dynamic-programming", "game-theory"] },
-        "1691": { "topicTags": ["array", "dynamic-programming", "sorting"] },
-        "1692": { "topicTags": ["dynamic-programming"] },
-        "1693": { "topicTags": ["database"] },
-        "1694": { "topicTags": ["string"] },
-        "1695": { "topicTags": ["array", "hash-table", "sliding-window"] },
-        "1696": { "topicTags": ["queue", "array", "dynamic-programming", "sliding-window", "monotonic-queue", "heap-priority-queue"] },
-        "1697": { "topicTags": ["union-find", "graph", "array", "sorting"] },
-        "1698": { "topicTags": ["trie", "string", "suffix-array", "hash-function", "rolling-hash"] },
-        "1699": { "topicTags": ["database"] },
-        "1700": { "topicTags": ["stack", "queue", "array", "simulation"] },
-        "1701": { "topicTags": ["array", "simulation"] },
-        "1702": { "topicTags": ["greedy", "string"] },
-        "1703": { "topicTags": ["greedy", "array", "prefix-sum", "sliding-window"] },
-        "1704": { "topicTags": ["string", "counting"] },
-        "1705": { "topicTags": ["greedy", "array", "heap-priority-queue"] },
-        "1706": { "topicTags": ["depth-first-search", "array", "dynamic-programming", "matrix", "simulation"] },
-        "1707": { "topicTags": ["bit-manipulation", "trie", "array"] },
-        "1708": { "topicTags": ["greedy", "array"] },
-        "1709": { "topicTags": ["database"] },
-        "1710": { "topicTags": ["greedy", "array", "sorting"] },
-        "1711": { "topicTags": ["array", "hash-table"] },
-        "1712": { "topicTags": ["array", "two-pointers", "binary-search", "prefix-sum"] },
-        "1713": { "topicTags": ["greedy", "array", "hash-table", "binary-search"] },
-        "1714": { "topicTags": ["array", "dynamic-programming"] },
-        "1715": { "topicTags": ["database"] },
-        "1716": { "topicTags": ["math"] },
-        "1717": { "topicTags": ["stack", "greedy", "string"] },
-        "1718": { "topicTags": ["array", "backtracking"] },
-        "1719": { "topicTags": ["tree", "graph", "topological-sort"] },
-        "1720": { "topicTags": ["bit-manipulation", "array"] },
-        "1721": { "topicTags": ["linked-list", "two-pointers"] },
-        "1722": { "topicTags": ["depth-first-search", "union-find", "array"] },
-        "1723": { "topicTags": ["bit-manipulation", "array", "dynamic-programming", "backtracking", "bitmask"] },
-        "1724": { "topicTags": ["union-find", "graph", "minimum-spanning-tree"] },
-        "1725": { "topicTags": ["array"] },
-        "1726": { "topicTags": ["array", "hash-table"] },
-        "1727": { "topicTags": ["greedy", "array", "matrix", "sorting"] },
-        "1728": { "topicTags": ["graph", "topological-sort", "memoization", "array", "math", "dynamic-programming", "game-theory", "matrix"] },
-        "1729": { "topicTags": ["database"] },
-        "1730": { "topicTags": ["breadth-first-search", "array", "matrix"] },
-        "1731": { "topicTags": ["database"] },
-        "1732": { "topicTags": ["array", "prefix-sum"] },
-        "1733": { "topicTags": ["greedy", "array"] },
-        "1734": { "topicTags": ["bit-manipulation", "array"] },
-        "1735": { "topicTags": ["array", "math", "dynamic-programming", "combinatorics", "number-theory"] },
-        "1736": { "topicTags": ["string"] },
-        "1737": { "topicTags": ["hash-table", "string", "counting", "prefix-sum"] },
-        "1738": { "topicTags": ["bit-manipulation", "array", "divide-and-conquer", "matrix", "prefix-sum", "quickselect", "heap-priority-queue"] },
-        "1739": { "topicTags": ["greedy", "math", "binary-search"] },
-        "1740": { "topicTags": ["tree", "depth-first-search", "breadth-first-search", "hash-table", "binary-tree"] },
-        "1741": { "topicTags": ["database"] },
-        "1742": { "topicTags": ["hash-table", "math", "counting"] },
-        "1743": { "topicTags": ["array", "hash-table"] },
-        "1744": { "topicTags": ["array", "prefix-sum"] },
-        "1745": { "topicTags": ["string", "dynamic-programming"] },
-        "1746": { "topicTags": ["array", "dynamic-programming"] },
-        "1747": { "topicTags": ["database"] },
-        "1748": { "topicTags": ["array", "hash-table", "counting"] },
-        "1749": { "topicTags": ["array", "dynamic-programming"] },
-        "1750": { "topicTags": ["two-pointers", "string"] },
-        "1751": { "topicTags": ["array", "binary-search", "dynamic-programming"] },
-        "1752": { "topicTags": ["array"] },
-        "1753": { "topicTags": ["greedy", "math", "heap-priority-queue"] },
-        "1754": { "topicTags": ["greedy", "two-pointers", "string"] },
-        "1755": { "topicTags": ["bit-manipulation", "array", "two-pointers", "dynamic-programming", "bitmask"] },
-        "1756": { "topicTags": ["stack", "design", "binary-indexed-tree", "array", "hash-table", "ordered-set"] },
-        "1757": { "topicTags": ["database"] },
-        "1758": { "topicTags": ["string"] },
-        "1759": { "topicTags": ["math", "string"] },
-        "1760": { "topicTags": ["array", "binary-search"] },
-        "1761": { "topicTags": ["graph"] },
-        "1762": { "topicTags": ["stack", "array", "monotonic-stack"] },
-        "1763": { "topicTags": ["bit-manipulation", "hash-table", "string", "divide-and-conquer", "sliding-window"] },
-        "1764": { "topicTags": ["greedy", "array", "string-matching"] },
-        "1765": { "topicTags": ["breadth-first-search", "array", "matrix"] },
-        "1766": { "topicTags": ["tree", "depth-first-search", "breadth-first-search", "math"] },
-        "1767": { "topicTags": ["database"] },
-        "1768": { "topicTags": ["two-pointers", "string"] },
-        "1769": { "topicTags": ["array", "string"] },
-        "1770": { "topicTags": ["array", "dynamic-programming"] },
-        "1771": { "topicTags": ["string", "dynamic-programming"] },
-        "1772": { "topicTags": ["array", "hash-table", "string", "sorting"] },
-        "1773": { "topicTags": ["array", "string"] },
-        "1774": { "topicTags": ["array", "dynamic-programming", "backtracking"] },
-        "1775": { "topicTags": ["greedy", "array", "hash-table", "counting"] },
-        "1776": { "topicTags": ["stack", "array", "math", "monotonic-stack", "heap-priority-queue"] },
-        "1777": { "topicTags": ["database"] },
-        "1778": { "topicTags": ["depth-first-search", "breadth-first-search", "graph", "interactive"] },
-        "1779": { "topicTags": ["array"] },
-        "1780": { "topicTags": ["math"] },
-        "1781": { "topicTags": ["hash-table", "string", "counting"] },
-        "1782": { "topicTags": ["graph", "two-pointers", "binary-search"] },
-        "1783": { "topicTags": ["database"] },
-        "1784": { "topicTags": ["string"] },
-        "1785": { "topicTags": ["greedy", "array"] },
-        "1786": { "topicTags": ["graph", "topological-sort", "dynamic-programming", "shortest-path", "heap-priority-queue"] },
-        "1787": { "topicTags": ["bit-manipulation", "array", "dynamic-programming"] },
-        "1788": { "topicTags": ["greedy", "array", "prefix-sum"] },
-        "1789": { "topicTags": ["database"] },
-        "1790": { "topicTags": ["hash-table", "string", "counting"] },
-        "1791": { "topicTags": ["graph"] },
-        "1792": { "topicTags": ["greedy", "array", "heap-priority-queue"] },
-        "1793": { "topicTags": ["stack", "array", "two-pointers", "binary-search", "monotonic-stack"] },
-        "1794": { "topicTags": ["greedy", "hash-table", "string"] },
-        "1795": { "topicTags": ["database"] },
-        "1796": { "topicTags": ["hash-table", "string"] },
-        "1797": { "topicTags": ["design", "hash-table"] },
-        "1798": { "topicTags": ["greedy", "array"] },
-        "1799": { "topicTags": ["bit-manipulation", "array", "math", "dynamic-programming", "backtracking", "bitmask", "number-theory"] },
-        "1800": { "topicTags": ["array"] },
-        "1801": { "topicTags": ["array", "simulation", "heap-priority-queue"] },
-        "1802": { "topicTags": ["greedy", "binary-search"] },
-        "1803": { "topicTags": ["bit-manipulation", "trie", "array"] },
-        "1804": { "topicTags": ["design", "trie", "hash-table", "string"] },
-        "1805": { "topicTags": ["hash-table", "string"] },
-        "1806": { "topicTags": ["array", "math", "simulation"] },
-        "1807": { "topicTags": ["array", "hash-table", "string"] },
-        "1808": { "topicTags": ["recursion", "math"] },
-        "1809": { "topicTags": ["database"] },
-        "1810": { "topicTags": ["depth-first-search", "breadth-first-search", "graph", "interactive", "heap-priority-queue"] },
-        "1811": { "topicTags": ["database"] },
-        "1812": { "topicTags": ["math", "string"] },
-        "1813": { "topicTags": ["array", "two-pointers", "string"] },
-        "1814": { "topicTags": ["array", "hash-table", "math", "counting"] },
-        "1815": { "topicTags": ["bit-manipulation", "memoization", "array", "dynamic-programming", "bitmask"] },
-        "1816": { "topicTags": ["array", "string"] },
-        "1817": { "topicTags": ["array", "hash-table"] },
-        "1818": { "topicTags": ["array", "binary-search", "ordered-set", "sorting"] },
-        "1819": { "topicTags": ["array", "math", "counting", "number-theory"] },
-        "1820": { "topicTags": ["array", "backtracking", "matrix"] },
-        "1821": { "topicTags": ["database"] },
-        "1822": { "topicTags": ["array", "math"] },
-        "1823": { "topicTags": ["recursion", "queue", "array", "math", "simulation"] },
-        "1824": { "topicTags": ["greedy", "array", "dynamic-programming"] },
-        "1825": { "topicTags": ["design", "queue", "data-stream", "ordered-set", "heap-priority-queue"] },
-        "1826": { "topicTags": ["array", "two-pointers"] },
-        "1827": { "topicTags": ["greedy", "array"] },
-        "1828": { "topicTags": ["geometry", "array", "math"] },
-        "1829": { "topicTags": ["bit-manipulation", "array", "prefix-sum"] },
-        "1830": { "topicTags": ["math", "string", "combinatorics"] },
-        "1831": { "topicTags": ["database"] },
-        "1832": { "topicTags": ["hash-table", "string"] },
-        "1833": { "topicTags": ["greedy", "array", "sorting"] },
-        "1834": { "topicTags": ["array", "sorting", "heap-priority-queue"] },
-        "1835": { "topicTags": ["bit-manipulation", "array", "math"] },
-        "1836": { "topicTags": ["hash-table", "linked-list"] },
-        "1837": { "topicTags": ["math"] },
-        "1838": { "topicTags": ["array", "binary-search", "prefix-sum", "sliding-window"] },
-        "1839": { "topicTags": ["string", "sliding-window"] },
-        "1840": { "topicTags": ["array", "math"] },
-        "1841": { "topicTags": ["database"] },
-        "1842": { "topicTags": ["two-pointers", "string"] },
-        "1843": { "topicTags": ["database"] },
-        "1844": { "topicTags": ["string"] },
-        "1845": { "topicTags": ["design", "heap-priority-queue"] },
-        "1846": { "topicTags": ["greedy", "array", "sorting"] },
-        "1847": { "topicTags": ["array", "binary-search", "sorting"] },
-        "1848": { "topicTags": ["array"] },
-        "1849": { "topicTags": ["string", "backtracking"] },
-        "1850": { "topicTags": ["greedy", "two-pointers", "string"] },
-        "1851": { "topicTags": ["array", "binary-search", "sorting", "line-sweep", "heap-priority-queue"] },
-        "1852": { "topicTags": ["array", "hash-table", "sliding-window"] },
-        "1853": { "topicTags": ["database"] },
-        "1854": { "topicTags": ["array", "counting"] },
-        "1855": { "topicTags": ["greedy", "array", "two-pointers", "binary-search"] },
-        "1856": { "topicTags": ["stack", "array", "prefix-sum", "monotonic-stack"] },
-        "1857": { "topicTags": ["graph", "topological-sort", "memoization", "hash-table", "dynamic-programming", "counting"] },
-        "1858": { "topicTags": ["depth-first-search", "trie"] },
-        "1859": { "topicTags": ["string", "sorting"] },
-        "1860": { "topicTags": ["simulation"] },
-        "1861": { "topicTags": ["array", "two-pointers", "matrix"] },
-        "1862": { "topicTags": ["array", "math", "binary-search", "prefix-sum"] },
-        "1863": { "topicTags": ["bit-manipulation", "array", "math", "backtracking", "combinatorics"] },
-        "1864": { "topicTags": ["greedy", "string"] },
-        "1865": { "topicTags": ["design", "array", "hash-table"] },
-        "1866": { "topicTags": ["math", "dynamic-programming", "combinatorics"] },
-        "1867": { "topicTags": ["database"] },
-        "1868": { "topicTags": ["array", "two-pointers"] },
-        "1869": { "topicTags": ["string"] },
-        "1870": { "topicTags": ["array", "binary-search"] },
-        "1871": { "topicTags": ["two-pointers", "string", "prefix-sum"] },
-        "1872": { "topicTags": ["array", "math", "dynamic-programming", "game-theory", "prefix-sum"] },
-        "1873": { "topicTags": ["database"] },
-        "1874": { "topicTags": ["greedy", "array", "sorting"] },
-        "1875": { "topicTags": ["database"] },
-        "1876": { "topicTags": ["hash-table", "string", "counting", "sliding-window"] },
-        "1877": { "topicTags": ["greedy", "array", "two-pointers", "sorting"] },
-        "1878": { "topicTags": ["array", "math", "matrix", "prefix-sum", "sorting", "heap-priority-queue"] },
-        "1879": { "topicTags": ["bit-manipulation", "array", "dynamic-programming", "bitmask"] },
-        "1880": { "topicTags": ["string"] },
-        "1881": { "topicTags": ["greedy", "string"] },
-        "1882": { "topicTags": ["array", "heap-priority-queue"] },
-        "1883": { "topicTags": ["array", "dynamic-programming"] },
-        "1884": { "topicTags": ["math", "dynamic-programming"] },
-        "1885": { "topicTags": ["array", "binary-search", "sorting"] },
-        "1886": { "topicTags": ["array", "matrix"] },
-        "1887": { "topicTags": ["array", "sorting"] },
-        "1888": { "topicTags": ["greedy", "string", "dynamic-programming", "sliding-window"] },
-        "1889": { "topicTags": ["array", "binary-search", "prefix-sum", "sorting"] },
-        "1890": { "topicTags": ["database"] },
-        "1891": { "topicTags": ["array", "binary-search"] },
-        "1892": { "topicTags": ["database"] },
-        "1893": { "topicTags": ["array", "hash-table", "prefix-sum"] },
-        "1894": { "topicTags": ["array", "binary-search", "prefix-sum", "simulation"] },
-        "1895": { "topicTags": ["array", "matrix", "prefix-sum"] },
-        "1896": { "topicTags": ["stack", "math", "string", "dynamic-programming"] },
-        "1897": { "topicTags": ["hash-table", "string", "counting"] },
-        "1898": { "topicTags": ["array", "string", "binary-search"] },
-        "1899": { "topicTags": ["greedy", "array"] },
-        "1900": { "topicTags": ["memoization", "dynamic-programming"] },
-        "1901": { "topicTags": ["array", "binary-search", "matrix"] },
-        "1902": { "topicTags": ["tree", "binary-search-tree", "binary-tree", "ordered-set"] },
-        "1903": { "topicTags": ["greedy", "math", "string"] },
-        "1904": { "topicTags": ["math", "string"] },
-        "1905": { "topicTags": ["depth-first-search", "breadth-first-search", "union-find", "array", "matrix"] },
-        "1906": { "topicTags": ["array", "hash-table"] },
-        "1907": { "topicTags": ["database"] },
-        "1908": { "topicTags": ["bit-manipulation", "brainteaser", "array", "math", "dynamic-programming", "game-theory"] },
-        "1909": { "topicTags": ["array"] },
-        "1910": { "topicTags": ["string"] },
-        "1911": { "topicTags": ["array", "dynamic-programming"] },
-        "1912": { "topicTags": ["design", "array", "hash-table", "ordered-set", "heap-priority-queue"] },
-        "1913": { "topicTags": ["array", "sorting"] },
-        "1914": { "topicTags": ["array", "matrix", "simulation"] },
-        "1915": { "topicTags": ["bit-manipulation", "hash-table", "string", "prefix-sum"] },
-        "1916": { "topicTags": ["tree", "graph", "topological-sort", "math", "dynamic-programming", "combinatorics"] },
-        "1917": { "topicTags": ["database"] },
-        "1918": { "topicTags": ["array", "binary-search", "sliding-window"] },
-        "1919": { "topicTags": ["database"] },
-        "1920": { "topicTags": ["array", "simulation"] },
-        "1921": { "topicTags": ["greedy", "array", "sorting"] },
-        "1922": { "topicTags": ["recursion", "math"] },
-        "1923": { "topicTags": ["array", "binary-search", "suffix-array", "hash-function", "rolling-hash"] },
-        "1924": { "topicTags": ["geometry", "array", "math"] },
-        "1925": { "topicTags": ["math", "enumeration"] },
-        "1926": { "topicTags": ["breadth-first-search", "array", "matrix"] },
-        "1927": { "topicTags": ["greedy", "math", "game-theory"] },
-        "1928": { "topicTags": ["graph", "dynamic-programming"] },
-        "1929": { "topicTags": ["array"] },
-        "1930": { "topicTags": ["hash-table", "string", "prefix-sum"] },
-        "1931": { "topicTags": ["dynamic-programming"] },
-        "1932": { "topicTags": ["tree", "depth-first-search", "hash-table", "binary-search", "binary-tree"] },
-        "1933": { "topicTags": ["string"] },
-        "1934": { "topicTags": ["database"] },
-        "1935": { "topicTags": ["hash-table", "string"] },
-        "1936": { "topicTags": ["greedy", "array"] },
-        "1937": { "topicTags": [] },
-        "1938": { "topicTags": [] },
-        "1939": { "topicTags": ["database"] },
-        "1940": { "topicTags": ["array", "hash-table", "counting"] },
-        "1941": { "topicTags": ["hash-table", "string", "counting"] },
-        "1942": { "topicTags": ["array", "ordered-set", "heap-priority-queue"] },
-        "1943": { "topicTags": ["array", "prefix-sum"] },
-        "1944": { "topicTags": ["stack", "array", "monotonic-stack"] },
-        "1945": { "topicTags": ["string", "simulation"] },
-        "1946": { "topicTags": ["greedy", "array", "string"] },
-        "1947": { "topicTags": ["bit-manipulation", "array", "dynamic-programming", "backtracking", "bitmask"] },
-        "1948": { "topicTags": ["trie", "array", "hash-table", "string", "hash-function"] },
-        "1949": { "topicTags": ["database"] },
-        "1950": { "topicTags": ["stack", "array", "monotonic-stack"] },
-        "1951": { "topicTags": ["database"] },
-        "1952": { "topicTags": ["math"] },
-        "1953": { "topicTags": ["greedy", "array"] },
-        "1954": { "topicTags": ["math", "binary-search"] },
-        "1955": { "topicTags": ["array", "dynamic-programming"] },
-        "1956": { "topicTags": ["geometry", "array", "math", "binary-search", "enumeration"] },
-        "1957": { "topicTags": ["string"] },
-        "1958": { "topicTags": ["array", "enumeration", "matrix"] },
-        "1959": { "topicTags": ["array", "dynamic-programming"] },
-        "1960": { "topicTags": ["string", "hash-function", "rolling-hash"] },
-        "1961": { "topicTags": ["array", "string"] },
-        "1962": { "topicTags": ["array", "heap-priority-queue"] },
-        "1963": { "topicTags": ["stack", "greedy", "two-pointers", "string"] },
-        "1964": { "topicTags": ["binary-indexed-tree", "array", "binary-search"] },
-        "1965": { "topicTags": ["database"] },
-        "1966": { "topicTags": ["array", "binary-search"] },
-        "1967": { "topicTags": ["string"] },
-        "1968": { "topicTags": ["greedy", "array", "sorting"] },
-        "1969": { "topicTags": ["greedy", "recursion", "math"] },
-        "1970": { "topicTags": ["depth-first-search", "breadth-first-search", "union-find", "array", "binary-search", "matrix"] },
-        "1971": { "topicTags": ["depth-first-search", "breadth-first-search", "union-find", "graph"] },
-        "1972": { "topicTags": ["database"] },
-        "1973": { "topicTags": [] },
-        "1974": { "topicTags": ["greedy", "string"] },
-        "1975": { "topicTags": ["greedy", "array", "matrix"] },
-        "1976": { "topicTags": ["graph", "topological-sort", "dynamic-programming", "shortest-path"] },
-        "1977": { "topicTags": ["string", "dynamic-programming", "suffix-array"] },
-        "1978": { "topicTags": [] },
-        "1979": { "topicTags": ["array", "math", "number-theory"] },
-        "1980": { "topicTags": ["array", "string", "backtracking"] },
-        "1981": { "topicTags": ["array", "dynamic-programming", "matrix"] },
-        "1982": { "topicTags": ["array", "divide-and-conquer"] },
-        "1983": { "topicTags": ["array", "hash-table", "prefix-sum"] },
-        "1984": { "topicTags": ["array", "sorting", "sliding-window"] },
-        "1985": { "topicTags": ["array", "string", "divide-and-conquer", "quickselect", "sorting", "heap-priority-queue"] },
-        "1986": { "topicTags": ["bit-manipulation", "array", "dynamic-programming", "backtracking", "bitmask"] },
-        "1987": { "topicTags": ["string", "dynamic-programming"] },
-        "1988": { "topicTags": [] },
-        "1989": { "topicTags": [] },
-        "1990": { "topicTags": [] },
-        "1991": { "topicTags": ["array", "prefix-sum"] },
-        "1992": { "topicTags": ["depth-first-search", "breadth-first-search", "array", "matrix"] },
-        "1993": { "topicTags": ["tree", "depth-first-search", "breadth-first-search", "design", "hash-table"] },
-        "1994": { "topicTags": ["bit-manipulation", "array", "math", "dynamic-programming", "bitmask"] },
-        "1995": { "topicTags": ["array", "enumeration"] },
-        "1996": { "topicTags": ["stack", "greedy", "array", "sorting", "monotonic-stack"] },
-        "1997": { "topicTags": ["array", "dynamic-programming"] },
-        "1998": { "topicTags": ["union-find", "array", "math", "sorting"] },
-        "1999": { "topicTags": [] },
-        "2000": { "topicTags": ["two-pointers", "string"] },
-        "2001": { "topicTags": ["array", "hash-table", "math", "counting", "number-theory"] },
-        "2002": { "topicTags": ["bit-manipulation", "string", "dynamic-programming", "backtracking", "bitmask"] },
-        "2003": { "topicTags": ["tree", "depth-first-search", "union-find", "dynamic-programming"] },
-        "2004": { "topicTags": [] },
-        "2005": { "topicTags": [] },
-        "2006": { "topicTags": ["array", "hash-table", "counting"] },
-        "2007": { "topicTags": ["greedy", "array", "hash-table", "sorting"] },
-        "2008": { "topicTags": ["array", "binary-search", "dynamic-programming", "sorting"] },
-        "2009": { "topicTags": ["array", "binary-search"] },
-        "2010": { "topicTags": [] },
-        "2011": { "topicTags": ["array", "string", "simulation"] },
-        "2012": { "topicTags": ["array"] },
-        "2013": { "topicTags": ["design", "array", "hash-table", "counting"] },
-        "2014": { "topicTags": ["greedy", "string", "backtracking", "counting", "enumeration"] },
-        "2015": { "topicTags": ["greedy", "array", "sorting", "heap-priority-queue"] },
-        "2016": { "topicTags": ["array"] },
-        "2017": { "topicTags": ["array", "matrix", "prefix-sum"] },
-        "2018": { "topicTags": ["array", "enumeration", "matrix"] },
-        "2019": { "topicTags": ["stack", "memoization", "array", "math", "string", "dynamic-programming"] },
-        "2020": { "topicTags": ["database"] },
-        "2021": { "topicTags": ["array", "ordered-set", "prefix-sum"] },
-        "2022": { "topicTags": ["array", "matrix", "simulation"] },
-        "2023": { "topicTags": ["array", "string"] },
-        "2024": { "topicTags": ["string", "binary-search", "prefix-sum", "sliding-window"] },
-        "2025": { "topicTags": ["array", "hash-table", "counting", "enumeration", "prefix-sum"] },
-        "2026": { "topicTags": ["database"] },
-        "2027": { "topicTags": ["greedy", "string"] },
-        "2028": { "topicTags": ["array", "math", "simulation"] },
-        "2029": { "topicTags": ["greedy", "array", "math", "counting", "game-theory"] },
-        "2030": { "topicTags": ["stack", "greedy", "string", "monotonic-stack"] },
-        "2031": { "topicTags": ["binary-indexed-tree", "segment-tree", "array", "binary-search", "divide-and-conquer", "ordered-set", "merge-sort"] },
-        "2032": { "topicTags": ["array", "hash-table"] },
-        "2033": { "topicTags": ["array", "math", "matrix", "sorting"] },
-        "2034": { "topicTags": ["design", "hash-table", "data-stream", "ordered-set", "heap-priority-queue"] },
-        "2035": { "topicTags": ["bit-manipulation", "array", "two-pointers", "binary-search", "dynamic-programming", "bitmask", "ordered-set"] },
-        "2036": { "topicTags": ["array", "dynamic-programming"] },
-        "2037": { "topicTags": ["array", "sorting"] },
-        "2038": { "topicTags": ["greedy", "math", "string", "game-theory"] },
-        "2039": { "topicTags": ["breadth-first-search", "graph", "array"] },
-        "2040": { "topicTags": ["array", "binary-search"] },
-        "2041": { "topicTags": ["database"] },
-        "2042": { "topicTags": ["string"] },
-        "2043": { "topicTags": ["design", "array", "hash-table", "simulation"] },
-        "2044": { "topicTags": ["bit-manipulation", "array", "backtracking"] },
-        "2045": { "topicTags": ["breadth-first-search", "graph", "shortest-path"] },
-        "2046": { "topicTags": ["linked-list", "two-pointers", "sorting"] },
-        "2047": { "topicTags": ["string"] },
-        "2048": { "topicTags": ["math", "backtracking", "enumeration"] },
-        "2049": { "topicTags": ["tree", "depth-first-search", "array", "binary-tree"] },
-        "2050": { "topicTags": ["graph", "topological-sort", "dynamic-programming"] },
-        "2051": { "topicTags": ["database"] },
-        "2052": { "topicTags": ["array", "dynamic-programming"] },
-        "2053": { "topicTags": ["array", "hash-table", "string", "counting"] },
-        "2054": { "topicTags": ["array", "binary-search", "dynamic-programming", "sorting", "heap-priority-queue"] },
-        "2055": { "topicTags": ["array", "string", "binary-search", "prefix-sum"] },
-        "2056": { "topicTags": ["array", "string", "backtracking", "simulation"] },
-        "2057": { "topicTags": ["array"] },
-        "2058": { "topicTags": ["linked-list"] },
-        "2059": { "topicTags": ["breadth-first-search", "array"] },
-        "2060": { "topicTags": ["string", "dynamic-programming"] },
-        "2061": { "topicTags": ["array", "matrix", "simulation"] },
-        "2062": { "topicTags": ["hash-table", "string"] },
-        "2063": { "topicTags": ["math", "string", "dynamic-programming", "combinatorics"] },
-        "2064": { "topicTags": ["array", "binary-search"] },
-        "2065": { "topicTags": ["graph", "array", "backtracking"] },
-        "2066": { "topicTags": ["database"] },
-        "2067": { "topicTags": ["string", "counting", "prefix-sum"] },
-        "2068": { "topicTags": ["hash-table", "string", "counting"] },
-        "2069": { "topicTags": ["design", "simulation"] },
-        "2070": { "topicTags": ["array", "binary-search", "sorting"] },
-        "2071": { "topicTags": ["greedy", "queue", "array", "binary-search", "sorting", "monotonic-queue"] },
-        "2072": { "topicTags": ["database"] },
-        "2073": { "topicTags": ["queue", "array", "simulation"] },
-        "2074": { "topicTags": ["linked-list"] },
-        "2075": { "topicTags": ["string", "simulation"] },
-        "2076": { "topicTags": ["union-find", "graph"] },
-        "2077": { "topicTags": ["graph"] },
-        "2078": { "topicTags": ["greedy", "array"] },
-        "2079": { "topicTags": ["array"] },
-        "2080": { "topicTags": ["design", "segment-tree", "array", "hash-table", "binary-search"] },
-        "2081": { "topicTags": ["math", "enumeration"] },
-        "2082": { "topicTags": ["database"] },
-        "2083": { "topicTags": ["hash-table", "math", "string", "counting", "prefix-sum"] },
-        "2084": { "topicTags": ["database"] },
-        "2085": { "topicTags": ["array", "hash-table", "string", "counting"] },
-        "2086": { "topicTags": ["greedy", "string", "dynamic-programming"] },
-        "2087": { "topicTags": ["greedy", "array", "matrix"] },
-        "2088": { "topicTags": ["array", "dynamic-programming", "matrix"] },
-        "2089": { "topicTags": ["array", "binary-search", "sorting"] },
-        "2090": { "topicTags": ["array", "sliding-window"] },
-        "2091": { "topicTags": ["greedy", "array"] },
-        "2092": { "topicTags": ["depth-first-search", "breadth-first-search", "union-find", "graph", "sorting"] },
-        "2093": { "topicTags": ["graph", "shortest-path"] },
-        "2094": { "topicTags": ["array", "hash-table", "enumeration", "sorting"] },
-        "2095": { "topicTags": ["linked-list", "two-pointers"] },
-        "2096": { "topicTags": ["tree", "depth-first-search", "string", "binary-tree"] },
-        "2097": { "topicTags": ["depth-first-search", "graph", "eulerian-circuit"] },
-        "2098": { "topicTags": ["greedy", "array", "sorting"] },
-        "2099": { "topicTags": ["array", "hash-table", "sorting", "heap-priority-queue"] },
-        "2100": { "topicTags": ["array", "dynamic-programming", "prefix-sum"] },
-        "2101": { "topicTags": ["depth-first-search", "breadth-first-search", "graph", "geometry", "array", "math"] },
-        "2102": { "topicTags": ["design", "data-stream", "ordered-set", "heap-priority-queue"] },
-        "2103": { "topicTags": ["hash-table", "string"] },
-        "2104": { "topicTags": ["stack", "array", "monotonic-stack"] },
-        "2105": { "topicTags": ["array", "two-pointers", "simulation"] },
-        "2106": { "topicTags": ["array", "binary-search", "prefix-sum", "sliding-window"] },
-        "2107": { "topicTags": ["array", "hash-table", "sliding-window"] },
-        "2108": { "topicTags": ["array", "two-pointers", "string"] },
-        "2109": { "topicTags": ["array", "string", "simulation"] },
-        "2110": { "topicTags": ["array", "math", "dynamic-programming"] },
-        "2111": { "topicTags": ["array", "binary-search"] },
-        "2112": { "topicTags": ["database"] },
-        "2113": { "topicTags": ["array"] },
-        "2114": { "topicTags": ["array", "string"] },
-        "2115": { "topicTags": ["graph", "topological-sort", "array", "hash-table", "string"] },
-        "2116": { "topicTags": ["stack", "greedy", "string"] },
-        "2117": { "topicTags": ["math"] },
-        "2118": { "topicTags": ["database"] },
-        "2119": { "topicTags": ["math"] },
-        "2120": { "topicTags": ["string", "simulation"] },
-        "2121": { "topicTags": ["array", "hash-table", "prefix-sum"] },
-        "2122": { "topicTags": ["array", "hash-table", "enumeration", "sorting"] },
-        "2123": { "topicTags": ["graph", "array", "matrix"] },
-        "2124": { "topicTags": ["string"] },
-        "2125": { "topicTags": ["array", "math", "string", "matrix"] },
-        "2126": { "topicTags": ["greedy", "array", "sorting"] },
-        "2127": { "topicTags": ["depth-first-search", "graph", "topological-sort"] },
-        "2128": { "topicTags": ["bit-manipulation", "array", "math", "matrix"] },
-        "2129": { "topicTags": ["string"] },
-        "2130": { "topicTags": ["stack", "linked-list", "two-pointers"] },
-        "2131": { "topicTags": ["greedy", "array", "hash-table", "string", "counting"] },
-        "2132": { "topicTags": ["greedy", "array", "matrix", "prefix-sum"] },
-        "2133": { "topicTags": ["array", "hash-table", "matrix"] },
-        "2134": { "topicTags": ["array", "sliding-window"] },
-        "2135": { "topicTags": ["bit-manipulation", "array", "hash-table", "string", "sorting"] },
-        "2136": { "topicTags": ["greedy", "array", "sorting"] },
-        "2137": { "topicTags": ["array", "binary-search"] },
-        "2138": { "topicTags": ["string", "simulation"] },
-        "2139": { "topicTags": ["greedy", "math"] },
-        "2140": { "topicTags": ["array", "dynamic-programming"] },
-        "2141": { "topicTags": ["greedy", "array", "binary-search", "sorting"] },
-        "2142": { "topicTags": ["database"] },
-        "2143": { "topicTags": ["array", "dynamic-programming"] },
-        "2144": { "topicTags": ["greedy", "array", "sorting"] },
-        "2145": { "topicTags": ["array", "prefix-sum"] },
-        "2146": { "topicTags": ["breadth-first-search", "array", "matrix", "sorting", "heap-priority-queue"] },
-        "2147": { "topicTags": ["math", "string", "dynamic-programming"] },
-        "2148": { "topicTags": ["array", "sorting"] },
-        "2149": { "topicTags": ["array", "two-pointers", "simulation"] },
-        "2150": { "topicTags": ["array", "hash-table", "counting"] },
-        "2151": { "topicTags": ["bit-manipulation", "array", "backtracking", "enumeration"] },
-        "2152": { "topicTags": ["bit-manipulation", "geometry", "array", "hash-table", "math", "dynamic-programming", "backtracking", "bitmask"] },
-        "2153": { "topicTags": ["database"] },
-        "2154": { "topicTags": ["array", "hash-table", "sorting", "simulation"] },
-        "2155": { "topicTags": ["array"] },
-        "2156": { "topicTags": ["string", "sliding-window", "hash-function", "rolling-hash"] },
-        "2157": { "topicTags": ["bit-manipulation", "union-find", "string"] },
-        "2158": { "topicTags": ["segment-tree", "array", "ordered-set"] },
-        "2159": { "topicTags": ["database"] },
-        "2160": { "topicTags": ["greedy", "math", "sorting"] },
-        "2161": { "topicTags": ["array", "two-pointers", "simulation"] },
-        "2162": { "topicTags": ["math", "enumeration"] },
-        "2163": { "topicTags": ["array", "dynamic-programming", "heap-priority-queue"] },
-        "2164": { "topicTags": ["array", "sorting"] },
-        "2165": { "topicTags": ["math", "sorting"] },
-        "2166": { "topicTags": ["design", "array", "hash-table"] },
-        "2167": { "topicTags": ["string", "dynamic-programming"] },
-        "2168": { "topicTags": ["hash-table", "string", "counting", "hash-function", "rolling-hash"] },
-        "2169": { "topicTags": ["math", "simulation"] },
-        "2170": { "topicTags": ["greedy", "array", "hash-table", "counting"] },
-        "2171": { "topicTags": ["array", "prefix-sum", "sorting"] },
-        "2172": { "topicTags": ["bit-manipulation", "array", "dynamic-programming", "bitmask"] },
-        "2173": { "topicTags": ["database"] },
-        "2174": { "topicTags": ["bit-manipulation", "breadth-first-search", "array", "matrix"] },
-        "2175": { "topicTags": ["database"] },
-        "2176": { "topicTags": ["array"] },
-        "2177": { "topicTags": ["math", "simulation"] },
-        "2178": { "topicTags": ["greedy", "math", "backtracking"] },
-        "2179": { "topicTags": ["binary-indexed-tree", "segment-tree", "array", "binary-search", "divide-and-conquer", "ordered-set", "merge-sort"] },
-        "2180": { "topicTags": ["math", "simulation"] },
-        "2181": { "topicTags": ["linked-list", "simulation"] },
-        "2182": { "topicTags": ["greedy", "string", "counting", "heap-priority-queue"] },
-        "2183": { "topicTags": ["array", "math", "number-theory"] },
-        "2184": { "topicTags": ["bit-manipulation", "array", "dynamic-programming", "bitmask"] },
-        "2185": { "topicTags": ["array", "string"] },
-        "2186": { "topicTags": ["hash-table", "string", "counting"] },
-        "2187": { "topicTags": ["array", "binary-search"] },
-        "2188": { "topicTags": ["array", "dynamic-programming"] },
-        "2189": { "topicTags": ["math", "dynamic-programming"] },
-        "2190": { "topicTags": ["array", "hash-table", "counting"] },
-        "2191": { "topicTags": ["array", "sorting"] },
-        "2192": { "topicTags": ["depth-first-search", "breadth-first-search", "graph", "topological-sort"] },
-        "2193": { "topicTags": ["greedy", "binary-indexed-tree", "two-pointers", "string"] },
-        "2194": { "topicTags": ["string"] },
-        "2195": { "topicTags": ["greedy", "array", "math", "sorting"] },
-        "2196": { "topicTags": ["tree", "depth-first-search", "breadth-first-search", "array", "hash-table", "binary-tree"] },
-        "2197": { "topicTags": ["stack", "array", "math", "number-theory"] },
-        "2198": { "topicTags": ["math"] },
-        "2199": { "topicTags": ["database"] },
-        "2200": { "topicTags": ["array"] },
-        "2201": { "topicTags": ["array", "hash-table", "simulation"] },
-        "2202": { "topicTags": ["greedy", "array"] },
-        "2203": { "topicTags": ["graph", "shortest-path"] },
-        "2204": { "topicTags": ["depth-first-search", "breadth-first-search", "union-find", "graph"] },
-        "2205": { "topicTags": ["database"] },
-        "2206": { "topicTags": ["bit-manipulation", "array", "hash-table", "counting"] },
-        "2207": { "topicTags": ["greedy", "string", "prefix-sum"] },
-        "2208": { "topicTags": ["greedy", "array", "heap-priority-queue"] },
-        "2209": { "topicTags": ["string", "dynamic-programming", "prefix-sum"] },
-        "2210": { "topicTags": ["array"] },
-        "2211": { "topicTags": ["stack", "string"] },
-        "2212": { "topicTags": ["bit-manipulation", "recursion", "array", "enumeration"] },
-        "2213": { "topicTags": ["segment-tree", "array", "string", "ordered-set"] },
-        "2214": { "topicTags": ["greedy", "array", "prefix-sum"] },
-        "2215": { "topicTags": ["array", "hash-table"] },
-        "2216": { "topicTags": ["stack", "greedy", "array"] },
-        "2217": { "topicTags": ["array", "math"] },
-        "2218": { "topicTags": ["array", "dynamic-programming", "prefix-sum"] },
-        "2219": { "topicTags": ["array", "prefix-sum"] },
-        "2220": { "topicTags": ["bit-manipulation"] },
-        "2221": { "topicTags": ["array", "math", "combinatorics", "simulation"] },
-        "2222": { "topicTags": ["string", "dynamic-programming", "prefix-sum"] },
-        "2223": { "topicTags": ["string", "binary-search", "string-matching", "suffix-array", "hash-function", "rolling-hash"] },
-        "2224": { "topicTags": ["greedy", "string"] },
-        "2225": { "topicTags": ["array", "hash-table", "counting", "sorting"] },
-        "2226": { "topicTags": ["array", "binary-search"] },
-        "2227": { "topicTags": ["design", "trie", "array", "hash-table", "string"] },
-        "2228": { "topicTags": ["database"] },
-        "2229": { "topicTags": ["array"] },
-        "2230": { "topicTags": ["database"] },
-        "2231": { "topicTags": ["sorting", "heap-priority-queue"] },
-        "2232": { "topicTags": ["string", "enumeration"] },
-        "2233": { "topicTags": ["greedy", "array", "heap-priority-queue"] },
-        "2234": { "topicTags": ["greedy", "array", "two-pointers", "binary-search", "sorting"] },
-        "2235": { "topicTags": ["math"] },
-        "2236": { "topicTags": ["tree", "binary-tree"] },
-        "2237": { "topicTags": ["array", "prefix-sum"] },
-        "2238": { "topicTags": ["database"] },
-        "2239": { "topicTags": ["array"] },
-        "2240": { "topicTags": ["math", "enumeration"] },
-        "2241": { "topicTags": ["greedy", "design", "array"] },
-        "2242": { "topicTags": ["graph", "array", "enumeration", "sorting"] },
-        "2243": { "topicTags": ["string", "simulation"] },
-        "2244": { "topicTags": ["greedy", "array", "hash-table", "counting"] },
-        "2245": { "topicTags": ["array", "matrix", "prefix-sum"] },
-        "2246": { "topicTags": ["tree", "depth-first-search", "graph", "topological-sort", "array", "string"] },
-        "2247": { "topicTags": ["bit-manipulation", "graph", "dynamic-programming", "bitmask"] },
-        "2248": { "topicTags": ["array", "hash-table", "counting"] },
-        "2249": { "topicTags": ["geometry", "array", "hash-table", "math", "enumeration"] },
-        "2250": { "topicTags": ["binary-indexed-tree", "array", "binary-search", "sorting"] },
-        "2251": { "topicTags": ["array", "hash-table", "binary-search", "ordered-set", "prefix-sum", "sorting"] },
-        "2252": { "topicTags": ["database"] },
-        "2253": { "topicTags": ["database"] },
-        "2254": { "topicTags": ["stack", "design", "hash-table", "ordered-set"] },
-        "2255": { "topicTags": ["array", "string"] },
-        "2256": { "topicTags": ["array", "prefix-sum"] },
-        "2257": { "topicTags": ["array", "matrix", "simulation"] },
-        "2258": { "topicTags": ["breadth-first-search", "array", "binary-search", "matrix"] },
-        "2259": { "topicTags": ["greedy", "string", "enumeration"] },
-        "2260": { "topicTags": ["array", "hash-table", "sliding-window"] },
-        "2261": { "topicTags": ["trie", "array", "hash-table", "enumeration", "hash-function", "rolling-hash"] },
-        "2262": { "topicTags": ["hash-table", "string", "dynamic-programming"] },
-        "2263": { "topicTags": ["greedy", "dynamic-programming"] },
-        "2264": { "topicTags": ["string"] },
-        "2265": { "topicTags": ["tree", "depth-first-search", "binary-tree"] },
-        "2266": { "topicTags": ["hash-table", "math", "string", "dynamic-programming"] },
-        "2267": { "topicTags": ["array", "dynamic-programming", "matrix"] },
-        "2268": { "topicTags": ["greedy", "array", "string", "counting", "sorting"] },
-        "2269": { "topicTags": ["math", "string", "sliding-window"] },
-        "2270": { "topicTags": [] },
-        "2271": { "topicTags": ["greedy", "array", "binary-search", "prefix-sum", "sorting"] },
-        "2272": { "topicTags": ["array", "dynamic-programming"] },
-        "2273": { "topicTags": ["array", "hash-table", "string", "sorting"] },
-        "2274": { "topicTags": ["array", "sorting"] },
-        "2275": { "topicTags": ["bit-manipulation", "array", "hash-table", "counting"] },
-        "2276": { "topicTags": ["design", "segment-tree", "ordered-set"] },
-        "2277": { "topicTags": ["tree", "depth-first-search", "breadth-first-search", "array"] },
-        "2278": { "topicTags": ["string"] },
-        "2279": { "topicTags": ["greedy", "array", "sorting"] },
-        "2280": { "topicTags": ["geometry", "array", "math", "number-theory", "sorting"] },
-        "2281": { "topicTags": ["stack", "array", "prefix-sum", "monotonic-stack"] },
-        "2282": { "topicTags": ["stack", "array", "matrix", "monotonic-stack"] },
-        "2283": { "topicTags": ["hash-table", "string", "counting"] },
-        "2284": { "topicTags": ["array", "hash-table", "string", "counting"] },
-        "2285": { "topicTags": ["greedy", "graph", "sorting", "heap-priority-queue"] },
-        "2286": { "topicTags": ["design", "binary-indexed-tree", "segment-tree", "binary-search"] },
-        "2287": { "topicTags": ["hash-table", "string", "counting"] },
-        "2288": { "topicTags": ["string"] },
-        "2289": { "topicTags": ["stack", "array", "linked-list", "monotonic-stack"] },
-        "2290": { "topicTags": ["breadth-first-search", "graph", "array", "matrix", "shortest-path", "heap-priority-queue"] },
-        "2291": { "topicTags": ["array", "dynamic-programming"] },
-        "2292": { "topicTags": ["database"] },
-        "2293": { "topicTags": ["array", "simulation"] },
-        "2294": { "topicTags": ["greedy", "array", "sorting"] },
-        "2295": { "topicTags": ["array", "hash-table", "simulation"] },
-        "2296": { "topicTags": ["stack", "design", "linked-list", "string", "doubly-linked-list", "simulation"] },
-        "2297": { "topicTags": ["stack", "graph", "array", "dynamic-programming", "shortest-path", "monotonic-stack"] },
-        "2298": { "topicTags": ["database"] },
-        "2299": { "topicTags": ["string"] },
-        "2300": { "topicTags": ["array", "two-pointers", "binary-search", "sorting"] },
-        "2301": { "topicTags": ["array", "hash-table", "string", "string-matching"] },
-        "2302": { "topicTags": ["array", "binary-search", "prefix-sum", "sliding-window"] },
-        "2303": { "topicTags": ["array", "simulation"] },
-        "2304": { "topicTags": ["array", "dynamic-programming", "matrix"] },
-        "2305": { "topicTags": ["bit-manipulation", "array", "dynamic-programming", "backtracking", "bitmask"] },
-        "2306": { "topicTags": ["bit-manipulation", "array", "hash-table", "string", "enumeration"] },
-        "2307": { "topicTags": ["depth-first-search", "union-find", "graph", "array"] },
-        "2308": { "topicTags": ["database"] },
-        "2309": { "topicTags": ["hash-table", "string", "enumeration"] },
-        "2310": { "topicTags": ["greedy", "math", "dynamic-programming", "enumeration"] },
-        "2311": { "topicTags": ["greedy", "memoization", "string", "dynamic-programming"] },
-        "2312": { "topicTags": ["memoization", "array", "dynamic-programming"] },
-        "2313": { "topicTags": ["tree", "depth-first-search", "dynamic-programming", "binary-tree"] },
-        "2314": { "topicTags": ["database"] },
-        "2315": { "topicTags": ["string"] },
-        "2316": { "topicTags": ["depth-first-search", "breadth-first-search", "union-find", "graph"] },
-        "2317": { "topicTags": ["bit-manipulation", "array", "math"] },
-        "2318": { "topicTags": ["memoization", "dynamic-programming"] },
-        "2319": { "topicTags": ["array", "matrix"] },
-        "2320": { "topicTags": ["dynamic-programming"] },
-        "2321": { "topicTags": ["array", "dynamic-programming"] },
-        "2322": { "topicTags": ["bit-manipulation", "tree", "depth-first-search", "array"] },
-        "2323": { "topicTags": ["greedy", "array", "sorting"] },
-        "2324": { "topicTags": ["database"] },
-        "2325": { "topicTags": ["hash-table", "string"] },
-        "2326": { "topicTags": ["array", "linked-list", "matrix", "simulation"] },
-        "2327": { "topicTags": ["queue", "dynamic-programming", "simulation"] },
-        "2328": { "topicTags": ["depth-first-search", "breadth-first-search", "graph", "topological-sort", "memoization", "array", "dynamic-programming", "matrix"] },
-        "2329": { "topicTags": ["database"] },
-        "2330": { "topicTags": ["two-pointers", "string"] },
-        "2331": { "topicTags": ["tree", "depth-first-search", "binary-search"] },
-        "2332": { "topicTags": ["array", "two-pointers", "binary-search", "sorting"] },
-        "2333": { "topicTags": ["array", "math", "sorting", "heap-priority-queue"] },
-        "2334": { "topicTags": ["stack", "union-find", "array", "monotonic-stack"] },
-        "2335": { "topicTags": ["greedy", "array", "heap-priority-queue"] },
-        "2336": { "topicTags": ["design", "hash-table", "heap-priority-queue"] },
-        "2337": { "topicTags": ["two-pointers", "string"] },
-        "2338": { "topicTags": ["math", "dynamic-programming", "combinatorics", "number-theory"] },
-        "2339": { "topicTags": ["database"] },
-        "2340": { "topicTags": ["greedy", "array"] },
-        "2341": { "topicTags": ["array", "hash-table", "counting"] },
-        "2342": { "topicTags": ["array", "hash-table", "sorting", "heap-priority-queue"] },
-        "2343": { "topicTags": ["array", "string", "divide-and-conquer", "quickselect", "radix-sort", "sorting", "heap-priority-queue"] },
-        "2344": { "topicTags": ["array", "math", "number-theory", "sorting", "heap-priority-queue"] },
-        "2345": { "topicTags": ["stack", "array", "sorting", "monotonic-stack"] },
-        "2346": { "topicTags": ["database"] },
-        "2347": { "topicTags": ["array", "hash-table", "counting"] },
-        "2348": { "topicTags": ["array", "math"] },
-        "2349": { "topicTags": ["design", "hash-table", "ordered-set", "heap-priority-queue"] },
-        "2350": { "topicTags": ["greedy", "array", "hash-table"] },
-        "2351": { "topicTags": ["hash-table", "string", "counting"] },
-        "2352": { "topicTags": ["array", "hash-table", "matrix", "simulation"] },
-        "2353": { "topicTags": ["design", "hash-table", "ordered-set", "heap-priority-queue"] },
-        "2354": { "topicTags": ["bit-manipulation", "array", "hash-table", "binary-search"] },
-        "2355": { "topicTags": ["stack", "array", "dynamic-programming", "monotonic-stack"] },
-        "2356": { "topicTags": ["database"] },
-        "2357": { "topicTags": ["array", "hash-table", "sorting", "simulation", "heap-priority-queue"] },
-        "2358": { "topicTags": ["greedy", "array", "math", "binary-search"] },
-        "2359": { "topicTags": ["depth-first-search", "graph"] },
-        "2360": { "topicTags": ["depth-first-search", "graph", "topological-sort"] },
-        "2361": { "topicTags": ["array", "dynamic-programming"] },
-        "2362": { "topicTags": ["database"] },
-        "2363": { "topicTags": ["array", "hash-table", "ordered-set", "sorting"] },
-        "2364": { "topicTags": ["array", "hash-table"] },
-        "2365": { "topicTags": ["array", "hash-table", "simulation"] },
-        "2366": { "topicTags": ["greedy", "array", "math"] },
-        "2367": { "topicTags": ["array", "hash-table", "two-pointers", "enumeration"] },
-        "2368": { "topicTags": ["tree", "depth-first-search", "breadth-first-search", "graph", "array", "hash-table"] },
-        "2369": { "topicTags": ["array", "dynamic-programming"] },
-        "2370": { "topicTags": ["hash-table", "string", "dynamic-programming"] },
-        "2371": { "topicTags": ["greedy", "union-find", "graph", "topological-sort", "array", "matrix", "sorting"] },
-        "2372": { "topicTags": ["database"] },
-        "2373": { "topicTags": ["array", "matrix"] },
-        "2374": { "topicTags": ["graph", "hash-table"] },
-        "2375": { "topicTags": ["stack", "greedy", "string", "backtracking"] },
-        "2376": { "topicTags": ["math", "dynamic-programming"] },
-        "2377": { "topicTags": ["database"] },
-        "2378": { "topicTags": ["tree", "depth-first-search", "dynamic-programming"] },
-        "2379": { "topicTags": ["string", "sliding-window"] },
-        "2380": { "topicTags": ["string", "dynamic-programming", "simulation"] },
-        "2381": { "topicTags": ["array", "string", "prefix-sum"] },
-        "2382": { "topicTags": ["union-find", "array", "ordered-set", "prefix-sum"] },
-        "2383": { "topicTags": ["greedy", "array"] },
-        "2384": { "topicTags": ["greedy", "hash-table", "string"] },
-        "2385": { "topicTags": ["tree", "depth-first-search", "breadth-first-search", "binary-tree"] },
-        "2386": { "topicTags": ["array", "sorting", "heap-priority-queue"] },
-        "2387": { "topicTags": ["array", "binary-search", "matrix"] },
-        "2388": { "topicTags": ["database"] },
-        "2389": { "topicTags": ["greedy", "array", "binary-search", "prefix-sum", "sorting"] },
-        "2390": { "topicTags": ["stack", "string", "simulation"] },
-        "2391": { "topicTags": ["array", "string", "prefix-sum"] },
-        "2392": { "topicTags": ["graph", "topological-sort", "array", "matrix"] },
-        "2393": { "topicTags": ["array", "math", "dynamic-programming"] },
-        "2394": { "topicTags": ["database"] },
-        "2395": { "topicTags": ["array", "hash-table"] },
-        "2396": { "topicTags": ["brainteaser", "math", "two-pointers"] },
-        "2397": { "topicTags": ["bit-manipulation", "array", "backtracking", "enumeration", "matrix"] },
-        "2398": { "topicTags": ["queue", "array", "binary-search", "prefix-sum", "sliding-window", "heap-priority-queue"] },
-        "2399": { "topicTags": ["array", "hash-table", "string"] },
-        "2400": { "topicTags": ["math", "dynamic-programming", "combinatorics"] },
-        "2401": { "topicTags": ["bit-manipulation", "array", "sliding-window"] },
-        "2402": { "topicTags": ["array", "sorting", "heap-priority-queue"] },
-        "2403": { "topicTags": ["bit-manipulation", "array", "dynamic-programming", "bitmask"] },
-        "2404": { "topicTags": ["array", "hash-table", "counting"] },
-        "2405": { "topicTags": ["greedy", "hash-table", "string"] },
-        "2406": { "topicTags": ["greedy", "array", "two-pointers", "prefix-sum", "sorting", "heap-priority-queue"] },
-        "2407": { "topicTags": ["binary-indexed-tree", "segment-tree", "queue", "array", "divide-and-conquer", "dynamic-programming", "monotonic-queue"] },
-        "2408": { "topicTags": ["design", "array", "hash-table", "string"] },
-        "2409": { "topicTags": ["math", "string"] },
-        "2410": { "topicTags": ["greedy", "array", "two-pointers", "sorting"] },
-        "2411": { "topicTags": ["bit-manipulation", "array", "binary-search", "sliding-window"] },
-        "2412": { "topicTags": ["greedy", "array", "sorting"] },
-        "2413": { "topicTags": ["math", "number-theory"] },
-        "2414": { "topicTags": ["string"] },
-        "2415": { "topicTags": ["tree", "depth-first-search", "breadth-first-search", "binary-tree"] },
-        "2416": { "topicTags": ["trie", "array", "string", "counting"] },
-        "2417": { "topicTags": ["math", "enumeration"] },
-        "2418": { "topicTags": ["array", "hash-table", "string", "sorting"] },
-        "2419": { "topicTags": ["bit-manipulation", "brainteaser", "array"] },
-        "2420": { "topicTags": ["array", "dynamic-programming", "prefix-sum"] },
-        "2421": { "topicTags": ["tree", "union-find", "graph", "array"] },
-        "LCP 01": { "topicTags": ["array"] },
-        "LCP 02": { "topicTags": ["array", "math", "number-theory", "simulation"] },
-        "LCP 03": { "topicTags": ["array", "hash-table", "simulation"] },
-        "LCP 04": { "topicTags": ["bit-manipulation", "graph", "array", "dynamic-programming", "bitmask"] },
-        "LCP 05": { "topicTags": ["binary-indexed-tree", "segment-tree", "array"] },
-        "LCP 06": { "topicTags": ["array", "math"] },
-        "LCP 07": { "topicTags": ["depth-first-search", "breadth-first-search", "graph", "dynamic-programming"] },
-        "LCP 08": { "topicTags": ["array", "binary-search", "sorting"] },
-        "LCP 09": { "topicTags": ["breadth-first-search", "segment-tree", "array", "dynamic-programming"] },
-        "LCP 10": { "topicTags": ["tree", "depth-first-search", "dynamic-programming", "binary-tree"] },
-        "LCP 11": { "topicTags": ["array", "hash-table", "math", "probability-and-statistics"] },
-        "LCP 12": { "topicTags": ["array", "binary-search"] },
-        "LCP 13": { "topicTags": ["bit-manipulation", "breadth-first-search", "array", "dynamic-programming", "bitmask", "matrix"] },
-        "LCP 14": { "topicTags": ["array", "math", "dynamic-programming", "number-theory"] },
-        "LCP 15": { "topicTags": ["greedy", "geometry", "array", "math"] },
-        "LCP 16": { "topicTags": ["graph", "geometry", "math"] },
-        "LCP 17": { "topicTags": ["math", "string", "simulation"] },
-        "LCP 18": { "topicTags": ["array", "two-pointers", "binary-search", "sorting"] },
-        "LCP 19": { "topicTags": ["string", "dynamic-programming"] },
-        "LCP 20": { "topicTags": ["memoization", "array", "dynamic-programming"] },
-        "LCP 21": { "topicTags": ["depth-first-search", "breadth-first-search", "graph", "topological-sort"] },
-        "LCP 22": { "topicTags": ["math"] },
-        "LCP 23": { "topicTags": ["queue", "array", "simulation"] },
-        "LCP 24": { "topicTags": ["array", "math", "heap-priority-queue"] },
-        "LCP 25": { "topicTags": ["math", "dynamic-programming", "combinatorics"] },
-        "LCP 26": { "topicTags": ["tree", "dynamic-programming", "binary-tree"] },
-        "LCP 27": { "topicTags": ["design", "segment-tree", "math", "ordered-set"] },
-        "LCP 28": { "topicTags": ["array", "two-pointers", "binary-search", "sorting"] },
-        "LCP 29": { "topicTags": ["math"] },
-        "LCP 30": { "topicTags": ["greedy", "array", "heap-priority-queue"] },
-        "LCP 31": { "topicTags": ["depth-first-search", "breadth-first-search", "array", "dynamic-programming", "matrix"] },
-        "LCP 32": { "topicTags": ["greedy", "array", "heap-priority-queue"] },
-        "LCP 33": { "topicTags": ["greedy", "array", "heap-priority-queue"] },
-        "LCP 34": { "topicTags": ["tree", "dynamic-programming", "binary-tree"] },
-        "LCP 35": { "topicTags": ["graph", "shortest-path", "heap-priority-queue"] },
-        "LCP 36": { "topicTags": ["array", "dynamic-programming", "sorting"] },
-        "LCP 37": { "topicTags": ["greedy", "geometry", "array", "math", "combinatorics", "sorting"] },
-        "LCP 38": { "topicTags": ["array", "dynamic-programming", "matrix"] },
-        "LCP 39": { "topicTags": ["array", "hash-table", "counting", "matrix"] },
-        "LCP 40": { "topicTags": ["greedy", "array", "sorting"] },
-        "LCP 41": { "topicTags": ["breadth-first-search", "array", "matrix"] },
-        "LCP 42": { "topicTags": ["geometry", "array", "hash-table", "math", "binary-search", "sorting"] },
-        "LCP 43": { "topicTags": ["array", "string", "dynamic-programming"] },
-        "LCP 44": { "topicTags": ["tree", "depth-first-search", "breadth-first-search", "hash-table", "binary-tree"] },
-        "LCP 45": { "topicTags": ["depth-first-search", "breadth-first-search", "memoization", "array", "dynamic-programming", "matrix"] },
-        "LCP 46": { "topicTags": ["graph", "array", "math"] },
-        "LCP 47": { "topicTags": ["array", "dynamic-programming"] },
-        "LCP 48": { "topicTags": ["array", "math", "enumeration", "game-theory"] },
-        "LCP 49": { "topicTags": ["bit-manipulation", "union-find", "array", "heap-priority-queue"] },
-        "LCP 50": { "topicTags": ["array", "simulation"] },
-        "LCP 51": { "topicTags": ["bit-manipulation", "array", "backtracking", "enumeration"] },
-        "LCP 52": { "topicTags": ["tree", "segment-tree", "binary-search-tree", "array", "binary-search", "binary-tree", "ordered-set"] },
-        "LCP 53": { "topicTags": ["bit-manipulation", "array", "dynamic-programming", "bitmask"] },
-        "LCP 54": { "topicTags": ["graph", "array", "biconnected-component"] },
-        "LCP 55": { "topicTags": ["array"] },
-        "LCP 56": { "topicTags": ["breadth-first-search", "graph", "array", "matrix", "shortest-path", "heap-priority-queue"] },
-        "LCP 57": { "topicTags": ["array", "dynamic-programming", "matrix", "sorting"] },
-        "LCP 58": { "topicTags": ["array", "backtracking", "matrix"] },
-        "LCP 59": { "topicTags": ["array", "dynamic-programming"] },
-        "LCP 60": { "topicTags": ["tree", "dynamic-programming", "binary-tree"] },
-        "LCP 61": { "topicTags": [] },
-        "LCP 62": { "topicTags": [] },
-        "LCP 63": { "topicTags": [] },
-        "LCP 64": { "topicTags": [] },
-        "LCP 65": { "topicTags": [] },
-        "LCS 01": { "topicTags": ["greedy", "math", "dynamic-programming"] },
-        "LCS 02": { "topicTags": ["greedy", "array", "hash-table", "sorting"] },
-        "LCS 03": { "topicTags": ["depth-first-search", "breadth-first-search", "union-find", "array", "matrix"] },
-        "剑指 Offer 03": { "topicTags": ["array", "hash-table", "sorting"] },
-        "剑指 Offer 04": { "topicTags": ["array", "binary-search", "divide-and-conquer", "matrix"] },
-        "剑指 Offer 05": { "topicTags": ["string"] },
-        "剑指 Offer 06": { "topicTags": ["stack", "recursion", "linked-list", "two-pointers"] },
-        "剑指 Offer 07": { "topicTags": ["tree", "array", "hash-table", "divide-and-conquer", "binary-tree"] },
-        "剑指 Offer 09": { "topicTags": ["stack", "design", "queue"] },
-        "剑指 Offer 10- I": { "topicTags": ["memoization", "math", "dynamic-programming"] },
-        "剑指 Offer 10- II": { "topicTags": ["memoization", "math", "dynamic-programming"] },
-        "剑指 Offer 11": { "topicTags": ["array", "binary-search"] },
-        "剑指 Offer 12": { "topicTags": ["array", "backtracking", "matrix"] },
-        "剑指 Offer 14- I": { "topicTags": ["math", "dynamic-programming"] },
-        "剑指 Offer 14- II": { "topicTags": ["math", "dynamic-programming"] },
-        "剑指 Offer 15": { "topicTags": ["bit-manipulation"] },
-        "剑指 Offer 16": { "topicTags": ["recursion", "math"] },
-        "剑指 Offer 17": { "topicTags": ["array", "math"] },
-        "剑指 Offer 18": { "topicTags": ["linked-list"] },
-        "剑指 Offer 19": { "topicTags": ["recursion", "string", "dynamic-programming"] },
-        "剑指 Offer 20": { "topicTags": ["string"] },
-        "剑指 Offer 21": { "topicTags": ["array", "two-pointers", "sorting"] },
-        "剑指 Offer 22": { "topicTags": ["linked-list", "two-pointers"] },
-        "剑指 Offer 24": { "topicTags": ["recursion", "linked-list"] },
-        "剑指 Offer 25": { "topicTags": ["recursion", "linked-list"] },
-        "剑指 Offer 26": { "topicTags": ["tree", "depth-first-search", "binary-tree"] },
-        "剑指 Offer 27": { "topicTags": ["tree", "depth-first-search", "breadth-first-search", "binary-tree"] },
-        "剑指 Offer 28": { "topicTags": ["tree", "depth-first-search", "breadth-first-search", "binary-tree"] },
-        "剑指 Offer 29": { "topicTags": ["array", "matrix", "simulation"] },
-        "剑指 Offer 30": { "topicTags": ["stack", "design"] },
-        "剑指 Offer 31": { "topicTags": ["stack", "array", "simulation"] },
-        "剑指 Offer 32 - I": { "topicTags": ["tree", "breadth-first-search", "binary-tree"] },
-        "剑指 Offer 32 - II": { "topicTags": ["tree", "breadth-first-search", "binary-tree"] },
-        "剑指 Offer 32 - III": { "topicTags": ["tree", "breadth-first-search", "binary-tree"] },
-        "剑指 Offer 33": { "topicTags": ["stack", "tree", "binary-search-tree", "recursion", "binary-tree", "monotonic-stack"] },
-        "剑指 Offer 34": { "topicTags": ["tree", "depth-first-search", "backtracking", "binary-tree"] },
-        "剑指 Offer 35": { "topicTags": ["hash-table", "linked-list"] },
-        "剑指 Offer 36": { "topicTags": ["stack", "tree", "depth-first-search", "binary-search-tree", "linked-list", "binary-tree", "doubly-linked-list"] },
-        "剑指 Offer 37": { "topicTags": ["tree", "depth-first-search", "breadth-first-search", "design", "string", "binary-tree"] },
-        "剑指 Offer 38": { "topicTags": ["string", "backtracking"] },
-        "剑指 Offer 39": { "topicTags": ["array", "hash-table", "divide-and-conquer", "counting", "sorting"] },
-        "剑指 Offer 40": { "topicTags": ["array", "divide-and-conquer", "quickselect", "sorting", "heap-priority-queue"] },
-        "剑指 Offer 41": { "topicTags": ["design", "two-pointers", "data-stream", "sorting", "heap-priority-queue"] },
-        "剑指 Offer 42": { "topicTags": ["array", "divide-and-conquer", "dynamic-programming"] },
-        "剑指 Offer 43": { "topicTags": ["recursion", "math", "dynamic-programming"] },
-        "剑指 Offer 44": { "topicTags": ["math", "binary-search"] },
-        "剑指 Offer 45": { "topicTags": ["greedy", "string", "sorting"] },
-        "剑指 Offer 46": { "topicTags": ["string", "dynamic-programming"] },
-        "剑指 Offer 47": { "topicTags": ["array", "dynamic-programming", "matrix"] },
-        "剑指 Offer 48": { "topicTags": ["hash-table", "string", "sliding-window"] },
-        "剑指 Offer 49": { "topicTags": ["hash-table", "math", "dynamic-programming", "heap-priority-queue"] },
-        "剑指 Offer 50": { "topicTags": ["queue", "hash-table", "string", "counting"] },
-        "剑指 Offer 51": { "topicTags": ["binary-indexed-tree", "segment-tree", "array", "binary-search", "divide-and-conquer", "ordered-set", "merge-sort"] },
-        "剑指 Offer 52": { "topicTags": ["hash-table", "linked-list", "two-pointers"] },
-        "剑指 Offer 53 - I": { "topicTags": ["array", "binary-search"] },
-        "剑指 Offer 53 - II": { "topicTags": ["bit-manipulation", "array", "hash-table", "math", "binary-search"] },
-        "剑指 Offer 54": { "topicTags": ["tree", "depth-first-search", "binary-search-tree", "binary-tree"] },
-        "剑指 Offer 55 - I": { "topicTags": ["tree", "depth-first-search", "breadth-first-search", "binary-tree"] },
-        "剑指 Offer 55 - II": { "topicTags": ["tree", "depth-first-search", "binary-tree"] },
-        "剑指 Offer 56 - I": { "topicTags": ["bit-manipulation", "array"] },
-        "剑指 Offer 56 - II": { "topicTags": ["bit-manipulation", "array"] },
-        "剑指 Offer 57": { "topicTags": ["array", "two-pointers", "binary-search"] },
-        "剑指 Offer 57 - II": { "topicTags": ["math", "two-pointers", "enumeration"] },
-        "剑指 Offer 58 - I": { "topicTags": ["two-pointers", "string"] },
-        "剑指 Offer 58 - II": { "topicTags": ["math", "two-pointers", "string"] },
-        "剑指 Offer 59 - I": { "topicTags": ["queue", "sliding-window", "monotonic-queue", "heap-priority-queue"] },
-        "剑指 Offer 60": { "topicTags": ["math", "dynamic-programming", "probability-and-statistics"] },
-        "剑指 Offer 61": { "topicTags": ["array", "sorting"] },
-        "剑指 Offer 62": { "topicTags": ["recursion", "math"] },
-        "剑指 Offer 63": { "topicTags": ["array", "dynamic-programming"] },
-        "剑指 Offer 64": { "topicTags": ["bit-manipulation", "recursion", "brainteaser"] },
-        "剑指 Offer 65": { "topicTags": ["bit-manipulation", "math"] },
-        "剑指 Offer 66": { "topicTags": ["array", "prefix-sum"] },
-        "剑指 Offer 67": { "topicTags": ["string"] },
-        "剑指 Offer 68 - I": { "topicTags": ["tree", "depth-first-search", "binary-search-tree", "binary-tree"] },
-        "剑指 Offer 68 - II": { "topicTags": ["tree", "depth-first-search", "binary-tree"] },
-        "剑指 Offer II 001": { "topicTags": ["bit-manipulation", "math"] },
-        "剑指 Offer II 002": { "topicTags": ["bit-manipulation", "math", "string", "simulation"] },
-        "剑指 Offer II 003": { "topicTags": ["bit-manipulation", "dynamic-programming"] },
-        "剑指 Offer II 004": { "topicTags": ["bit-manipulation", "array"] },
-        "剑指 Offer II 005": { "topicTags": ["bit-manipulation", "array", "string"] },
-        "剑指 Offer II 006": { "topicTags": ["array", "two-pointers", "binary-search"] },
-        "剑指 Offer II 007": { "topicTags": ["array", "two-pointers", "sorting"] },
-        "剑指 Offer II 008": { "topicTags": ["array", "binary-search", "prefix-sum", "sliding-window"] },
-        "剑指 Offer II 009": { "topicTags": ["array", "sliding-window"] },
-        "剑指 Offer II 010": { "topicTags": ["array", "hash-table", "prefix-sum"] },
-        "剑指 Offer II 011": { "topicTags": ["array", "hash-table", "prefix-sum"] },
-        "剑指 Offer II 012": { "topicTags": ["array", "prefix-sum"] },
-        "剑指 Offer II 013": { "topicTags": ["design", "array", "matrix", "prefix-sum"] },
-        "剑指 Offer II 014": { "topicTags": ["hash-table", "two-pointers", "string", "sliding-window"] },
-        "剑指 Offer II 015": { "topicTags": ["hash-table", "string", "sliding-window"] },
-        "剑指 Offer II 016": { "topicTags": ["hash-table", "string", "sliding-window"] },
-        "剑指 Offer II 017": { "topicTags": ["hash-table", "string", "sliding-window"] },
-        "剑指 Offer II 018": { "topicTags": ["two-pointers", "string"] },
-        "剑指 Offer II 019": { "topicTags": ["greedy", "two-pointers", "string"] },
-        "剑指 Offer II 020": { "topicTags": ["string", "dynamic-programming"] },
-        "剑指 Offer II 021": { "topicTags": ["linked-list", "two-pointers"] },
-        "剑指 Offer II 022": { "topicTags": ["hash-table", "linked-list", "two-pointers"] },
-        "剑指 Offer II 023": { "topicTags": ["hash-table", "linked-list", "two-pointers"] },
-        "剑指 Offer II 024": { "topicTags": ["recursion", "linked-list"] },
-        "剑指 Offer II 025": { "topicTags": ["stack", "linked-list", "math"] },
-        "剑指 Offer II 026": { "topicTags": ["stack", "recursion", "linked-list", "two-pointers"] },
-        "剑指 Offer II 027": { "topicTags": ["stack", "recursion", "linked-list", "two-pointers"] },
-        "剑指 Offer II 028": { "topicTags": ["depth-first-search", "linked-list", "doubly-linked-list"] },
-        "剑指 Offer II 029": { "topicTags": ["linked-list"] },
-        "剑指 Offer II 030": { "topicTags": ["design", "array", "hash-table", "math", "randomized"] },
-        "剑指 Offer II 031": { "topicTags": ["design", "hash-table", "linked-list", "doubly-linked-list"] },
-        "剑指 Offer II 032": { "topicTags": ["hash-table", "string", "sorting"] },
-        "剑指 Offer II 033": { "topicTags": ["array", "hash-table", "string", "sorting"] },
-        "剑指 Offer II 034": { "topicTags": ["array", "hash-table", "string"] },
-        "剑指 Offer II 035": { "topicTags": ["array", "math", "string", "sorting"] },
-        "剑指 Offer II 036": { "topicTags": ["stack", "array", "math"] },
-        "剑指 Offer II 037": { "topicTags": ["stack", "array"] },
-        "剑指 Offer II 038": { "topicTags": ["stack", "array", "monotonic-stack"] },
-        "剑指 Offer II 039": { "topicTags": ["stack", "array", "monotonic-stack"] },
-        "剑指 Offer II 040": { "topicTags": ["stack", "array", "dynamic-programming", "matrix", "monotonic-stack"] },
-        "剑指 Offer II 041": { "topicTags": ["design", "queue", "array", "data-stream"] },
-        "剑指 Offer II 042": { "topicTags": ["design", "queue", "data-stream"] },
-        "剑指 Offer II 043": { "topicTags": ["tree", "breadth-first-search", "design", "binary-tree"] },
-        "剑指 Offer II 044": { "topicTags": ["tree", "depth-first-search", "breadth-first-search", "binary-tree"] },
-        "剑指 Offer II 045": { "topicTags": ["tree", "depth-first-search", "breadth-first-search", "binary-tree"] },
-        "剑指 Offer II 046": { "topicTags": ["tree", "depth-first-search", "breadth-first-search", "binary-tree"] },
-        "剑指 Offer II 047": { "topicTags": ["tree", "depth-first-search", "binary-tree"] },
-        "剑指 Offer II 048": { "topicTags": ["tree", "depth-first-search", "breadth-first-search", "design", "string", "binary-tree"] },
-        "剑指 Offer II 049": { "topicTags": ["tree", "depth-first-search", "binary-tree"] },
-        "剑指 Offer II 050": { "topicTags": ["tree", "depth-first-search", "binary-tree"] },
-        "剑指 Offer II 051": { "topicTags": ["tree", "depth-first-search", "dynamic-programming", "binary-tree"] },
-        "剑指 Offer II 052": { "topicTags": ["stack", "tree", "depth-first-search", "binary-search-tree", "binary-tree"] },
-        "剑指 Offer II 053": { "topicTags": ["tree", "depth-first-search", "binary-search-tree", "binary-tree"] },
-        "剑指 Offer II 054": { "topicTags": ["tree", "depth-first-search", "binary-search-tree", "binary-tree"] },
-        "剑指 Offer II 055": { "topicTags": ["stack", "tree", "design", "binary-search-tree", "binary-tree", "iterator"] },
-        "剑指 Offer II 056": { "topicTags": ["tree", "depth-first-search", "breadth-first-search", "binary-search-tree", "hash-table", "two-pointers", "binary-tree"] },
-        "剑指 Offer II 057": { "topicTags": ["array", "bucket-sort", "ordered-set", "sorting", "sliding-window"] },
-        "剑指 Offer II 058": { "topicTags": ["design", "segment-tree", "binary-search", "ordered-set"] },
-        "剑指 Offer II 059": { "topicTags": ["tree", "design", "binary-search-tree", "binary-tree", "data-stream", "heap-priority-queue"] },
-        "剑指 Offer II 060": { "topicTags": ["array", "hash-table", "divide-and-conquer", "bucket-sort", "counting", "quickselect", "sorting", "heap-priority-queue"] },
-        "剑指 Offer II 061": { "topicTags": ["array", "heap-priority-queue"] },
-        "剑指 Offer II 062": { "topicTags": ["design", "trie", "hash-table", "string"] },
-        "剑指 Offer II 063": { "topicTags": ["trie", "array", "hash-table", "string"] },
-        "剑指 Offer II 064": { "topicTags": ["design", "trie", "hash-table", "string"] },
-        "剑指 Offer II 065": { "topicTags": ["trie", "array", "hash-table", "string"] },
-        "剑指 Offer II 066": { "topicTags": ["design", "trie", "hash-table", "string"] },
-        "剑指 Offer II 067": { "topicTags": ["bit-manipulation", "trie", "array", "hash-table"] },
-        "剑指 Offer II 068": { "topicTags": ["array", "binary-search"] },
-        "剑指 Offer II 069": { "topicTags": ["array", "binary-search"] },
-        "剑指 Offer II 070": { "topicTags": ["array", "binary-search"] },
-        "剑指 Offer II 071": { "topicTags": ["math", "binary-search", "prefix-sum", "randomized"] },
-        "剑指 Offer II 072": { "topicTags": ["math", "binary-search"] },
-        "剑指 Offer II 073": { "topicTags": ["array", "binary-search"] },
-        "剑指 Offer II 074": { "topicTags": ["array", "sorting"] },
-        "剑指 Offer II 075": { "topicTags": ["array", "hash-table", "counting-sort", "sorting"] },
-        "剑指 Offer II 076": { "topicTags": ["array", "divide-and-conquer", "quickselect", "sorting", "heap-priority-queue"] },
-        "剑指 Offer II 077": { "topicTags": ["linked-list", "two-pointers", "divide-and-conquer", "sorting", "merge-sort"] },
-        "剑指 Offer II 078": { "topicTags": ["linked-list", "divide-and-conquer", "heap-priority-queue", "merge-sort"] },
-        "剑指 Offer II 079": { "topicTags": ["bit-manipulation", "array", "backtracking"] },
-        "剑指 Offer II 080": { "topicTags": ["array", "backtracking"] },
-        "剑指 Offer II 081": { "topicTags": ["array", "backtracking"] },
-        "剑指 Offer II 082": { "topicTags": ["array", "backtracking"] },
-        "剑指 Offer II 083": { "topicTags": ["array", "backtracking"] },
-        "剑指 Offer II 084": { "topicTags": ["array", "backtracking"] },
-        "剑指 Offer II 085": { "topicTags": ["string", "dynamic-programming", "backtracking"] },
-        "剑指 Offer II 086": { "topicTags": ["depth-first-search", "breadth-first-search", "graph", "hash-table"] },
-        "剑指 Offer II 087": { "topicTags": ["string", "backtracking"] },
-        "剑指 Offer II 088": { "topicTags": ["array", "dynamic-programming"] },
-        "剑指 Offer II 089": { "topicTags": ["array", "dynamic-programming"] },
-        "剑指 Offer II 090": { "topicTags": ["array", "dynamic-programming"] },
-        "剑指 Offer II 091": { "topicTags": ["array", "dynamic-programming"] },
-        "剑指 Offer II 092": { "topicTags": ["string", "dynamic-programming"] },
-        "剑指 Offer II 093": { "topicTags": ["array", "hash-table", "dynamic-programming"] },
-        "剑指 Offer II 094": { "topicTags": ["string", "dynamic-programming"] },
-        "剑指 Offer II 095": { "topicTags": ["string", "dynamic-programming"] },
-        "剑指 Offer II 096": { "topicTags": ["string", "dynamic-programming"] },
-        "剑指 Offer II 097": { "topicTags": ["string", "dynamic-programming"] },
-        "剑指 Offer II 098": { "topicTags": ["math", "dynamic-programming", "combinatorics"] },
-        "剑指 Offer II 099": { "topicTags": ["array", "dynamic-programming", "matrix"] },
-        "剑指 Offer II 100": { "topicTags": ["array", "dynamic-programming"] },
-        "剑指 Offer II 101": { "topicTags": ["math", "string", "simulation"] },
-        "剑指 Offer II 102": { "topicTags": ["array", "dynamic-programming", "backtracking"] },
-        "剑指 Offer II 103": { "topicTags": ["breadth-first-search", "array", "dynamic-programming"] },
-        "剑指 Offer II 104": { "topicTags": ["array", "dynamic-programming"] },
-        "剑指 Offer II 105": { "topicTags": ["depth-first-search", "breadth-first-search", "union-find", "array", "matrix"] },
-        "剑指 Offer II 106": { "topicTags": ["depth-first-search", "breadth-first-search", "union-find", "graph"] },
-        "剑指 Offer II 107": { "topicTags": ["breadth-first-search", "array", "dynamic-programming", "matrix"] },
-        "剑指 Offer II 108": { "topicTags": ["breadth-first-search", "hash-table", "string"] },
-        "剑指 Offer II 109": { "topicTags": ["breadth-first-search", "array", "hash-table", "string"] },
-        "剑指 Offer II 110": { "topicTags": ["depth-first-search", "breadth-first-search", "graph", "backtracking"] },
-        "剑指 Offer II 111": { "topicTags": ["depth-first-search", "breadth-first-search", "union-find", "graph", "array", "shortest-path"] },
-        "剑指 Offer II 112": { "topicTags": ["depth-first-search", "breadth-first-search", "graph", "topological-sort", "memoization", "array", "dynamic-programming", "matrix"] },
-        "剑指 Offer II 113": { "topicTags": ["depth-first-search", "breadth-first-search", "graph", "topological-sort"] },
-        "剑指 Offer II 114": { "topicTags": ["depth-first-search", "breadth-first-search", "graph", "topological-sort", "array", "string"] },
-        "剑指 Offer II 115": { "topicTags": ["graph", "topological-sort", "array"] },
-        "剑指 Offer II 116": { "topicTags": ["depth-first-search", "breadth-first-search", "union-find", "graph"] },
-        "剑指 Offer II 117": { "topicTags": ["depth-first-search", "breadth-first-search", "union-find", "array", "string"] },
-        "剑指 Offer II 118": { "topicTags": ["depth-first-search", "breadth-first-search", "union-find", "graph"] },
-        "剑指 Offer II 119": { "topicTags": ["union-find", "array", "hash-table"] },
-        "面试题 01.01": { "topicTags": ["bit-manipulation", "hash-table", "string", "sorting"] },
-        "面试题 01.02": { "topicTags": ["hash-table", "string", "sorting"] },
-        "面试题 01.03": { "topicTags": ["string"] },
-        "面试题 01.04": { "topicTags": ["bit-manipulation", "hash-table", "string"] },
-        "面试题 01.05": { "topicTags": ["two-pointers", "string"] },
-        "面试题 01.06": { "topicTags": ["two-pointers", "string"] },
-        "面试题 01.07": { "topicTags": ["array", "math", "matrix"] },
-        "面试题 01.08": { "topicTags": ["array", "hash-table", "matrix"] },
-        "面试题 01.09": { "topicTags": ["string", "string-matching"] },
-        "面试题 02.01": { "topicTags": ["hash-table", "linked-list", "two-pointers"] },
-        "面试题 02.02": { "topicTags": ["linked-list", "two-pointers"] },
-        "面试题 02.03": { "topicTags": ["linked-list"] },
-        "面试题 02.04": { "topicTags": ["linked-list", "two-pointers"] },
-        "面试题 02.05": { "topicTags": ["recursion", "linked-list", "math"] },
-        "面试题 02.06": { "topicTags": ["stack", "recursion", "linked-list", "two-pointers"] },
-        "面试题 02.07": { "topicTags": ["hash-table", "linked-list", "two-pointers"] },
-        "面试题 02.08": { "topicTags": ["hash-table", "linked-list", "two-pointers"] },
-        "面试题 03.01": { "topicTags": ["stack", "design", "array"] },
-        "面试题 03.02": { "topicTags": ["stack", "design"] },
-        "面试题 03.03": { "topicTags": ["stack", "design", "linked-list"] },
-        "面试题 03.04": { "topicTags": ["stack", "design", "queue"] },
-        "面试题 03.05": { "topicTags": ["stack", "design", "monotonic-stack"] },
-        "面试题 03.06": { "topicTags": ["design", "queue"] },
-        "面试题 04.01": { "topicTags": ["depth-first-search", "breadth-first-search", "union-find", "graph"] },
-        "面试题 04.02": { "topicTags": ["tree", "binary-search-tree", "array", "divide-and-conquer", "binary-tree"] },
-        "面试题 04.03": { "topicTags": ["tree", "breadth-first-search", "linked-list", "binary-tree"] },
-        "面试题 04.04": { "topicTags": ["tree", "depth-first-search", "binary-tree"] },
-        "面试题 04.05": { "topicTags": ["tree", "depth-first-search", "binary-search-tree", "binary-tree"] },
-        "面试题 04.06": { "topicTags": ["tree", "depth-first-search", "binary-search-tree", "binary-tree"] },
-        "面试题 04.08": { "topicTags": ["tree", "depth-first-search", "binary-tree"] },
-        "面试题 04.09": { "topicTags": ["tree", "binary-search-tree", "backtracking", "binary-tree"] },
-        "面试题 04.10": { "topicTags": ["tree", "depth-first-search", "binary-tree", "string-matching", "hash-function"] },
-        "面试题 04.12": { "topicTags": ["tree", "depth-first-search", "binary-tree"] },
-        "面试题 05.01": { "topicTags": ["bit-manipulation"] },
-        "面试题 05.02": { "topicTags": ["bit-manipulation", "math", "string"] },
-        "面试题 05.03": { "topicTags": ["bit-manipulation", "dynamic-programming"] },
-        "面试题 05.04": { "topicTags": ["bit-manipulation"] },
-        "面试题 05.06": { "topicTags": ["bit-manipulation"] },
-        "面试题 05.07": { "topicTags": ["bit-manipulation"] },
-        "面试题 05.08": { "topicTags": ["bit-manipulation", "array", "math"] },
-        "面试题 08.01": { "topicTags": ["memoization", "math", "dynamic-programming"] },
-        "面试题 08.02": { "topicTags": ["array", "dynamic-programming", "backtracking", "matrix"] },
-        "面试题 08.03": { "topicTags": ["array", "binary-search"] },
-        "面试题 08.04": { "topicTags": ["bit-manipulation", "array", "backtracking"] },
-        "面试题 08.05": { "topicTags": ["bit-manipulation", "recursion", "math"] },
-        "面试题 08.06": { "topicTags": ["recursion", "array"] },
-        "面试题 08.07": { "topicTags": ["string", "backtracking"] },
-        "面试题 08.08": { "topicTags": ["string", "backtracking"] },
-        "面试题 08.09": { "topicTags": ["string", "dynamic-programming", "backtracking"] },
-        "面试题 08.10": { "topicTags": ["depth-first-search", "breadth-first-search", "array", "matrix"] },
-        "面试题 08.11": { "topicTags": ["array", "math", "dynamic-programming"] },
-        "面试题 08.12": { "topicTags": ["array", "backtracking"] },
-        "面试题 08.13": { "topicTags": ["array", "dynamic-programming", "sorting"] },
-        "面试题 08.14": { "topicTags": ["memoization", "string", "dynamic-programming"] },
-        "面试题 10.01": { "topicTags": ["array", "two-pointers", "sorting"] },
-        "面试题 10.02": { "topicTags": ["array", "hash-table", "string", "sorting"] },
-        "面试题 10.03": { "topicTags": ["array", "binary-search"] },
-        "面试题 10.05": { "topicTags": ["array", "string", "binary-search"] },
-        "面试题 10.09": { "topicTags": ["array", "binary-search", "divide-and-conquer", "matrix"] },
-        "面试题 10.10": { "topicTags": ["design", "binary-indexed-tree", "binary-search", "data-stream"] },
-        "面试题 10.11": { "topicTags": ["greedy", "array", "sorting"] },
-        "面试题 16.01": { "topicTags": ["bit-manipulation", "math"] },
-        "面试题 16.02": { "topicTags": ["design", "trie", "array", "hash-table", "string"] },
-        "面试题 16.03": { "topicTags": ["geometry", "math"] },
-        "面试题 16.04": { "topicTags": ["array", "counting", "matrix"] },
-        "面试题 16.05": { "topicTags": ["math"] },
-        "面试题 16.06": { "topicTags": ["array", "two-pointers", "binary-search", "sorting"] },
-        "面试题 16.07": { "topicTags": ["bit-manipulation", "brainteaser", "math"] },
-        "面试题 16.08": { "topicTags": ["recursion", "math", "string"] },
-        "面试题 16.09": { "topicTags": ["design", "math"] },
-        "面试题 16.10": { "topicTags": ["array", "counting"] },
-        "面试题 16.11": { "topicTags": ["array", "math"] },
-        "面试题 16.13": { "topicTags": ["geometry", "math"] },
-        "面试题 16.14": { "topicTags": ["geometry", "array", "hash-table", "math"] },
-        "面试题 16.15": { "topicTags": ["hash-table", "string", "counting"] },
-        "面试题 16.16": { "topicTags": ["stack", "greedy", "array", "two-pointers", "sorting", "monotonic-stack"] },
-        "面试题 16.17": { "topicTags": ["array", "divide-and-conquer", "dynamic-programming"] },
-        "面试题 16.18": { "topicTags": ["math", "string", "backtracking", "enumeration"] },
-        "面试题 16.19": { "topicTags": ["depth-first-search", "breadth-first-search", "union-find", "array", "matrix"] },
-        "面试题 16.20": { "topicTags": ["array", "hash-table", "string"] },
-        "面试题 16.21": { "topicTags": ["array", "hash-table", "binary-search", "sorting"] },
-        "面试题 16.22": { "topicTags": ["array", "hash-table", "string", "matrix", "simulation"] },
-        "面试题 16.24": { "topicTags": ["array", "hash-table", "two-pointers", "counting", "sorting"] },
-        "面试题 16.25": { "topicTags": ["design", "hash-table", "linked-list", "doubly-linked-list"] },
-        "面试题 16.26": { "topicTags": ["stack", "math", "string"] },
-        "面试题 17.01": { "topicTags": ["bit-manipulation", "math"] },
-        "面试题 17.04": { "topicTags": ["bit-manipulation", "array", "hash-table", "math", "sorting"] },
-        "面试题 17.05": { "topicTags": ["array", "hash-table", "prefix-sum"] },
-        "面试题 17.06": { "topicTags": ["recursion", "math", "dynamic-programming"] },
-        "面试题 17.07": { "topicTags": ["depth-first-search", "breadth-first-search", "union-find", "array", "hash-table", "string", "counting"] },
-        "面试题 17.08": { "topicTags": ["array", "binary-search", "dynamic-programming", "sorting"] },
-        "面试题 17.09": { "topicTags": ["hash-table", "math", "dynamic-programming", "heap-priority-queue"] },
-        "面试题 17.10": { "topicTags": ["array", "counting"] },
-        "面试题 17.11": { "topicTags": ["array", "string"] },
-        "面试题 17.12": { "topicTags": ["stack", "tree", "depth-first-search", "binary-search-tree", "linked-list", "binary-tree"] },
-        "面试题 17.13": { "topicTags": ["trie", "array", "hash-table", "string", "dynamic-programming", "hash-function", "rolling-hash"] },
-        "面试题 17.14": { "topicTags": ["array", "divide-and-conquer", "quickselect", "sorting", "heap-priority-queue"] },
-        "面试题 17.15": { "topicTags": ["trie", "array", "hash-table", "string"] },
-        "面试题 17.16": { "topicTags": ["array", "dynamic-programming"] },
-        "面试题 17.17": { "topicTags": ["trie", "array", "hash-table", "string", "string-matching", "sliding-window"] },
-        "面试题 17.18": { "topicTags": ["array", "hash-table", "sliding-window"] },
-        "面试题 17.19": { "topicTags": ["bit-manipulation", "array", "hash-table"] },
-        "面试题 17.20": { "topicTags": ["design", "two-pointers", "data-stream", "sorting", "heap-priority-queue"] },
-        "面试题 17.21": { "topicTags": ["stack", "array", "two-pointers", "dynamic-programming", "monotonic-stack"] },
-        "面试题 17.22": { "topicTags": ["breadth-first-search", "hash-table", "string", "backtracking"] },
-        "面试题 17.23": { "topicTags": ["array", "dynamic-programming", "matrix"] },
-        "面试题 17.24": { "topicTags": ["array", "dynamic-programming", "matrix", "prefix-sum"] },
-        "面试题 17.25": { "topicTags": ["trie", "array", "string", "backtracking"] },
-        "面试题 17.26": { "topicTags": ["array", "hash-table", "sorting"] },
-        "面试题13": { "topicTags": ["depth-first-search", "breadth-first-search", "dynamic-programming"] },
-        "面试题59 - II": { "topicTags": ["design", "queue", "monotonic-queue"] }
-    };
-
-    private tags_name = {
-        'array': '数组',
-        'hash-table': '哈希表',
-        'recursion': '递归',
-        'linked-list': '链表',
-        'math': '数学',
-        'string': '字符串',
-        'sliding-window': '滑动窗口',
-        'binary-search': '二分搜索',
-        'divide-and-conquer': '分治',
-        'dynamic-programming': '动态规划',
-        'greedy': '贪心',
-        'two-pointers': '双指针',
-        'sorting': '排序',
-        'backtracking': '回溯',
-        'stack': '堆',
-        'heap-priority-queue': '优先级队列',
-        'merge-sort': '归并排序',
-        'string-matching': '字符串匹配',
-        'bit-manipulation': '位操作',
-        'matrix': '矩阵',
-        'monotonic-stack': '单调栈',
-        'simulation': '模拟',
-        'combinatorics': '组合学',
-        'memoization': '记忆',
-        'tree': '树',
-        'depth-first-search': '深度优先搜索',
-        'binary-tree': '二叉树',
-        'binary-search-tree': '二叉搜索树',
-        'breadth-first-search': '广度优先搜索',
-        'union-find': '并查集',
-        'graph': '图',
-        'trie': '尝试',
-        'design': '设计',
-        'doubly-linked-list': '双向链表',
-        'geometry': '几何学',
-        'interactive': '交互的',
-        'bucket-sort': '桶排序',
-        'radix-sort': '基数排序',
-        'counting': '数数',
-        'data-stream': '数据流',
-        'iterator': '迭代器',
-        'database': '数据库',
-        'hash-function': '散列函数',
-        'rolling-hash': '滚动哈希',
-        'shell': '脚本',
-        'enumeration': '枚举',
-        'number-theory': '数论',
-        'topological-sort': '拓扑排序',
-        'prefix-sum': '前缀和',
-        'quickselect': '快速选择',
-        'binary-indexed-tree': '二进制索引树',
-        'segment-tree': '线段树',
-        'ordered-set': '有序集',
-        'line-sweep': '扫描线',
-        'queue': '队列',
-        'monotonic-queue': '单调队列',
-        'counting-sort': '计数排序',
-        'brainteaser': '脑筋急转弯',
-        'game-theory': '博弈论',
-        'eulerian-circuit': '欧拉回路',
-        'randomized': '随机',
-        'reservoir-sampling': '水库采样',
-        'shortest-path': '最短路径',
-        'bitmask': '位掩码',
-        'rejection-sampling': '拒绝抽样',
-        'probability-and-statistics': '概率和统计',
-        'suffix-array': '后缀数组',
-        'concurrency': '并发',
-        'minimum-spanning-tree': '最小生成树',
-        'biconnected-component': '双连接组件',
-        'strongly-connected-component': '强连接组件'
-
-    };
-    public getTagsData(fid: string): Array {
-        return (this.tagsData[fid]?.topicTags || []).map(p => {
-            return this.tags_name[p];
-        });
-    }
-
+  private tags_name = {
+    array: "数组",
+    "hash-table": "哈希表",
+    recursion: "递归",
+    "linked-list": "链表",
+    math: "数学",
+    string: "字符串",
+    "sliding-window": "滑动窗口",
+    "binary-search": "二分搜索",
+    "divide-and-conquer": "分治",
+    "dynamic-programming": "动态规划",
+    greedy: "贪心",
+    "two-pointers": "双指针",
+    sorting: "排序",
+    backtracking: "回溯",
+    stack: "堆",
+    "heap-priority-queue": "优先级队列",
+    "merge-sort": "归并排序",
+    "string-matching": "字符串匹配",
+    "bit-manipulation": "位操作",
+    matrix: "矩阵",
+    "monotonic-stack": "单调栈",
+    simulation: "模拟",
+    combinatorics: "组合学",
+    memoization: "记忆",
+    tree: "树",
+    "depth-first-search": "深度优先搜索",
+    "binary-tree": "二叉树",
+    "binary-search-tree": "二叉搜索树",
+    "breadth-first-search": "广度优先搜索",
+    "union-find": "并查集",
+    graph: "图",
+    trie: "尝试",
+    design: "设计",
+    "doubly-linked-list": "双向链表",
+    geometry: "几何学",
+    interactive: "交互的",
+    "bucket-sort": "桶排序",
+    "radix-sort": "基数排序",
+    counting: "数数",
+    "data-stream": "数据流",
+    iterator: "迭代器",
+    database: "数据库",
+    "hash-function": "散列函数",
+    "rolling-hash": "滚动哈希",
+    shell: "脚本",
+    enumeration: "枚举",
+    "number-theory": "数论",
+    "topological-sort": "拓扑排序",
+    "prefix-sum": "前缀和",
+    quickselect: "快速选择",
+    "binary-indexed-tree": "二进制索引树",
+    "segment-tree": "线段树",
+    "ordered-set": "有序集",
+    "line-sweep": "扫描线",
+    queue: "队列",
+    "monotonic-queue": "单调队列",
+    "counting-sort": "计数排序",
+    brainteaser: "脑筋急转弯",
+    "game-theory": "博弈论",
+    "eulerian-circuit": "欧拉回路",
+    randomized: "随机",
+    "reservoir-sampling": "水库采样",
+    "shortest-path": "最短路径",
+    bitmask: "位掩码",
+    "rejection-sampling": "拒绝抽样",
+    "probability-and-statistics": "概率和统计",
+    "suffix-array": "后缀数组",
+    concurrency: "并发",
+    "minimum-spanning-tree": "最小生成树",
+    "biconnected-component": "双连接组件",
+    "strongly-connected-component": "强连接组件",
+  };
+  public getTagsData(fid: string): Array {
+    return (this.tagsData[fid]?.topicTags || []).map((p) => {
+      return this.tags_name[p];
+    });
+  }
 }
 
-
 export const tagsDao: TagsDao = new TagsDao();
-
-
-
-
-
-
diff --git a/src/extension.ts b/src/extension.ts
index 5ddec09..7b11ec2 100644
--- a/src/extension.ts
+++ b/src/extension.ts
@@ -7,7 +7,6 @@
  * Copyright (c) 2022 ccagml . All rights reserved.
  */
 
-
 import { ExtensionContext, window, commands, Uri } from "vscode";
 import { fileButtonController } from "./controller/FileButtonController";
 import { treeViewController } from "./controller/TreeViewController";
@@ -29,63 +28,75 @@ import { DialogType } from "./model/Model";
 
 // 激活插件
 export async function activate(context: ExtensionContext): Promise {
-    try {
-
-        // 初始化控制器
-        mainContorller.initialize(context);
-        // 检查node环境
-        await mainContorller.checkNodeEnv(context);
-        // 事件监听
-        eventController.add_event();
+  try {
+    // 初始化控制器
+    mainContorller.initialize(context);
+    // 检查node环境
+    await mainContorller.checkNodeEnv(context);
+    // 事件监听
+    eventController.add_event();
 
-        // 资源管理
-        context.subscriptions.push(
-            statusBarService,
-            logOutput,
-            previewService,
-            submissionService,
-            solutionService,
-            executeService,
-            markdownService,
-            fileButtonController,
-            treeViewController,
-            window.registerFileDecorationProvider(treeItemDecorationService),
-            window.createTreeView("leetCodeExplorer", { treeDataProvider: treeDataService, showCollapseAll: true }),
-            commands.registerCommand("leetcode.deleteCache", () => mainContorller.deleteCache()),
-            commands.registerCommand("leetcode.toggleLeetCodeCn", () => treeViewController.switchEndpoint()),
-            commands.registerCommand("leetcode.signin", () => loginContorller.signIn()),
-            commands.registerCommand("leetcode.signout", () => loginContorller.signOut()),
-            commands.registerCommand("leetcode.previewProblem", (node: NodeModel) => treeViewController.previewProblem(node)),
-            commands.registerCommand("leetcode.showProblem", (node: NodeModel) => treeViewController.showProblem(node)),
-            commands.registerCommand("leetcode.pickOne", () => treeViewController.pickOne()),
-            commands.registerCommand("leetcode.deleteAllCache", () => loginContorller.deleteAllCache()),
-            commands.registerCommand("leetcode.searchScoreRange", () => treeViewController.searchScoreRange()),
-            commands.registerCommand("leetcode.searchProblem", () => treeViewController.searchProblem()),
-            commands.registerCommand("leetcode.showSolution", (input: NodeModel | Uri) => treeViewController.showSolution(input)),
-            commands.registerCommand("leetcode.refreshExplorer", () => treeDataService.refresh()),
-            commands.registerCommand("leetcode.testSolution", (uri?: Uri) => treeViewController.testSolution(uri)),
-            commands.registerCommand("leetcode.testSolutionDefault", (uri?: Uri, allCase?: boolean) => treeViewController.testSolutionDefault(uri, allCase)),
-            commands.registerCommand("leetcode.submitSolution", (uri?: Uri) => treeViewController.submitSolution(uri)),
-            commands.registerCommand("leetcode.switchDefaultLanguage", () => treeViewController.switchDefaultLanguage()),
-            commands.registerCommand("leetcode.addFavorite", (node: NodeModel) => treeViewController.addFavorite(node)),
-            commands.registerCommand("leetcode.removeFavorite", (node: NodeModel) => treeViewController.removeFavorite(node)),
-            commands.registerCommand("leetcode.problems.sort", () => treeViewController.switchSortingStrategy()),
-        );
+    // 资源管理
+    context.subscriptions.push(
+      statusBarService,
+      logOutput,
+      previewService,
+      submissionService,
+      solutionService,
+      executeService,
+      markdownService,
+      fileButtonController,
+      treeViewController,
+      window.registerFileDecorationProvider(treeItemDecorationService),
+      window.createTreeView("leetCodeExplorer", {
+        treeDataProvider: treeDataService,
+        showCollapseAll: true,
+      }),
+      commands.registerCommand("leetcode.deleteCache", () => mainContorller.deleteCache()),
+      commands.registerCommand("leetcode.toggleLeetCodeCn", () => treeViewController.switchEndpoint()),
+      commands.registerCommand("leetcode.signin", () => loginContorller.signIn()),
+      commands.registerCommand("leetcode.signout", () => loginContorller.signOut()),
+      commands.registerCommand("leetcode.previewProblem", (node: NodeModel) => treeViewController.previewProblem(node)),
+      commands.registerCommand("leetcode.showProblem", (node: NodeModel) => treeViewController.showProblem(node)),
+      commands.registerCommand("leetcode.pickOne", () => treeViewController.pickOne()),
+      commands.registerCommand("leetcode.deleteAllCache", () => loginContorller.deleteAllCache()),
+      commands.registerCommand("leetcode.searchScoreRange", () => treeViewController.searchScoreRange()),
+      commands.registerCommand("leetcode.searchProblem", () => treeViewController.searchProblem()),
+      commands.registerCommand("leetcode.showSolution", (input: NodeModel | Uri) =>
+        treeViewController.showSolution(input)
+      ),
+      commands.registerCommand("leetcode.refreshExplorer", () => treeDataService.refresh()),
+      commands.registerCommand("leetcode.testSolution", (uri?: Uri) => treeViewController.testSolution(uri)),
+      commands.registerCommand("leetcode.testSolutionDefault", (uri?: Uri, allCase?: boolean) =>
+        treeViewController.testSolutionDefault(uri, allCase)
+      ),
+      commands.registerCommand("leetcode.testSolutionArea", (uri?: Uri, testCase?: string) =>
+        treeViewController.testSolutionArea(uri, testCase)
+      ),
+      commands.registerCommand("leetcode.submitSolution", (uri?: Uri) => treeViewController.submitSolution(uri)),
+      commands.registerCommand("leetcode.switchDefaultLanguage", () => treeViewController.switchDefaultLanguage()),
+      commands.registerCommand("leetcode.addFavorite", (node: NodeModel) => treeViewController.addFavorite(node)),
+      commands.registerCommand("leetcode.removeFavorite", (node: NodeModel) => treeViewController.removeFavorite(node)),
+      commands.registerCommand("leetcode.problems.sort", () => treeViewController.switchSortingStrategy())
+    );
 
-        // 设置站点
-        await executeService.switchEndpoint(getLeetCodeEndpoint());
-        // 获取登录状态
-        await loginContorller.getLoginStatus();
-    } catch (error) {
-        logOutput.appendLine(error.toString());
-        promptForOpenOutputChannel("Extension initialization failed. Please open output channel for details.", DialogType.error);
-    }
+    // 设置站点
+    await executeService.switchEndpoint(getLeetCodeEndpoint());
+    // 获取登录状态
+    await loginContorller.getLoginStatus();
+  } catch (error) {
+    logOutput.appendLine(error.toString());
+    promptForOpenOutputChannel(
+      "Extension initialization failed. Please open output channel for details.",
+      DialogType.error
+    );
+  }
 }
 
 export function deactivate(): void {
-    // Do nothing.
-    if (0) {
-        let a = 0;
-        console.log(a);
-    }
+  // Do nothing.
+  if (0) {
+    let a = 0;
+    console.log(a);
+  }
 }
diff --git a/src/model/Model.ts b/src/model/Model.ts
index 170dea0..6e775df 100644
--- a/src/model/Model.ts
+++ b/src/model/Model.ts
@@ -7,277 +7,269 @@
  * Copyright (c) 2022 ccagml . All rights reserved.
  */
 
-
 import { ViewColumn, QuickPickItem, MessageItem } from "vscode";
 
 export interface IQuickItemEx extends QuickPickItem {
-    value: T;
+  value: T;
 }
 
 export enum UserStatus {
-    SignedIn = 1,
-    SignedOut = 2,
+  SignedIn = 1,
+  SignedOut = 2,
 }
 
 export const loginArgsMapping: Map = new Map([
-    ["LeetCode", "-l"],
-    ["Cookie", "-c"],
-    ["GitHub", "-g"],
-    ["LinkedIn", "-i"],
+  ["LeetCode", "-l"],
+  ["Cookie", "-c"],
+  ["GitHub", "-g"],
+  ["LinkedIn", "-i"],
 ]);
 
 export const languages: string[] = [
-    "bash",
-    "c",
-    "cpp",
-    "csharp",
-    "golang",
-    "java",
-    "javascript",
-    "kotlin",
-    "mysql",
-    "php",
-    "python",
-    "python3",
-    "ruby",
-    "rust",
-    "scala",
-    "swift",
-    "typescript",
+  "bash",
+  "c",
+  "cpp",
+  "csharp",
+  "golang",
+  "java",
+  "javascript",
+  "kotlin",
+  "mysql",
+  "php",
+  "python",
+  "python3",
+  "ruby",
+  "rust",
+  "scala",
+  "swift",
+  "typescript",
 ];
 
 export const langExt: Map = new Map([
-    ["bash", "sh"],
-    ["c", "c"],
-    ["cpp", "cpp"],
-    ["csharp", "cs"],
-    ["golang", "go"],
-    ["java", "java"],
-    ["javascript", "js"],
-    ["kotlin", "kt"],
-    ["mysql", "sql"],
-    ["php", "php"],
-    ["python", "py"],
-    ["python3", "py"],
-    ["ruby", "rb"],
-    ["rust", "rs"],
-    ["scala", "scala"],
-    ["swift", "swift"],
-    ["typescript", "ts"],
+  ["bash", "sh"],
+  ["c", "c"],
+  ["cpp", "cpp"],
+  ["csharp", "cs"],
+  ["golang", "go"],
+  ["java", "java"],
+  ["javascript", "js"],
+  ["kotlin", "kt"],
+  ["mysql", "sql"],
+  ["php", "php"],
+  ["python", "py"],
+  ["python3", "py"],
+  ["ruby", "rb"],
+  ["rust", "rs"],
+  ["scala", "scala"],
+  ["swift", "swift"],
+  ["typescript", "ts"],
 ]);
 
 export enum ProblemState {
-    AC = 1,
-    NotAC = 2,
-    Unknown = 3,
+  AC = 1,
+  NotAC = 2,
+  Unknown = 3,
 }
 
 export enum Endpoint {
-    LeetCode = "leetcode",
-    LeetCodeCN = "leetcode-cn",
+  LeetCode = "leetcode",
+  LeetCodeCN = "leetcode-cn",
 }
 
 export enum RootNodeSort {
-    ZERO = 0,
-    Day = 1,
-    All = 2,
-    Difficulty = 3,
-    Tag = 4,
-    Company = 5,
-    Favorite = 6,
-    Choice = 7,
-    Score = 8,
-    ScoreRange = 9,
-    Context = 9,
+  ZERO = 0,
+  Day = 1,
+  All = 2,
+  Difficulty = 3,
+  Tag = 4,
+  Company = 5,
+  Favorite = 6,
+  Choice = 7,
+  Score = 8,
+  ScoreRange = 9,
+  Context = 9,
 }
 
-
 export interface IProblem {
-    isFavorite: boolean;
-    locked: boolean;
-    state: ProblemState;
-    id: string; // 题目编号 fid
-    qid: string;
-    name: string;
-    difficulty: string;
-    passRate: string;
-    companies: string[];
-    tags: string[];
-    scoreData: IScoreData | undefined; // 分数的结构
-    isSearchResult: boolean;
-    input: string;
-    rootNodeSortId: RootNodeSort;
-    todayData: ITodayData | undefined;
+  isFavorite: boolean;
+  locked: boolean;
+  state: ProblemState;
+  id: string; // 题目编号 fid
+  qid: string;
+  name: string;
+  difficulty: string;
+  passRate: string;
+  companies: string[];
+  tags: string[];
+  scoreData: IScoreData | undefined; // 分数的结构
+  isSearchResult: boolean;
+  input: string;
+  rootNodeSortId: RootNodeSort;
+  todayData: ITodayData | undefined;
 }
 
 export interface ITodayData {
-    date: string; // 日期
-    userStatus: string; // 状态   'NOT_START' 'FINISH'
+  date: string; // 日期
+  userStatus: string; // 状态   'NOT_START' 'FINISH'
 }
 
-
 export interface IScoreData {
-    Rating: number; // 分数
-    score: string; // rank分
-    ID: number;   // 题目ID
-    ContestID_en: string; // 周赛名称
-    ProblemIndex: string; // 周赛第几题
-    ContestSlug: string; // 周赛名称
+  Rating: number; // 分数
+  score: string; // rank分
+  ID: number; // 题目ID
+  ContestID_en: string; // 周赛名称
+  ProblemIndex: string; // 周赛第几题
+  ContestSlug: string; // 周赛名称
 }
 
 export const defaultProblem: IProblem = {
-    isFavorite: false,
-    locked: false,
-    state: ProblemState.Unknown,
-    id: "",
-    qid: "",
-    name: "",
-    difficulty: "",
-    passRate: "",
-    companies: [] as string[],
-    tags: [] as string[],
-    scoreData: undefined,
-    isSearchResult: false,
-    input: "",
-    rootNodeSortId: RootNodeSort.ZERO,
-    todayData: undefined
+  isFavorite: false,
+  locked: false,
+  state: ProblemState.Unknown,
+  id: "",
+  qid: "",
+  name: "",
+  difficulty: "",
+  passRate: "",
+  companies: [] as string[],
+  tags: [] as string[],
+  scoreData: undefined,
+  isSearchResult: false,
+  input: "",
+  rootNodeSortId: RootNodeSort.ZERO,
+  todayData: undefined,
 };
 
 export enum Category {
-    All = "All",
-    Difficulty = "Difficulty",
-    Tag = "Tag",
-    Company = "Company",
-    Favorite = "Favorite",
-    Score = "Score",
-    Choice = "Choice",
-
+  All = "All",
+  Difficulty = "Difficulty",
+  Tag = "Tag",
+  Company = "Company",
+  Favorite = "Favorite",
+  Score = "Score",
+  Choice = "Choice",
 }
 
 export const supportedPlugins: string[] = [
-    // "company",
-    "solution.discuss",
-    "leetcode.cn",
+  // "company",
+  "solution.discuss",
+  "leetcode.cn",
 ];
 
 export enum DescriptionConfiguration {
-    InWebView = "In Webview",
-    InFileComment = "In File Comment",
-    Both = "Both",
-    None = "None",
+  InWebView = "In Webview",
+  InFileComment = "In File Comment",
+  Both = "Both",
+  None = "None",
 }
 
 export const leetcodeHasInited: string = "leetcode.hasInited";
 
 export enum SortingStrategy {
-    None = "None",
-    AcceptanceRateAsc = "Acceptance Rate (Ascending)",
-    AcceptanceRateDesc = "Acceptance Rate (Descending)",
-    FrequencyAsc = "Frequency (Ascending)",
-    FrequencyDesc = "Frequency (Descending)",
-    ScoreAsc = "Score (Ascending)",
-    ScoreDesc = "Score (Descending)",
-    IDDesc = "ID (Descending)"
+  None = "None",
+  AcceptanceRateAsc = "Acceptance Rate (Ascending)",
+  AcceptanceRateDesc = "Acceptance Rate (Descending)",
+  FrequencyAsc = "Frequency (Ascending)",
+  FrequencyDesc = "Frequency (Descending)",
+  ScoreAsc = "Score (Ascending)",
+  ScoreDesc = "Score (Descending)",
+  IDDesc = "ID (Descending)",
 }
 
-
 export const SORT_ORDER: SortingStrategy[] = [
-    SortingStrategy.None,
-    SortingStrategy.AcceptanceRateAsc,
-    SortingStrategy.AcceptanceRateDesc,
-    SortingStrategy.ScoreAsc,
-    SortingStrategy.ScoreDesc,
-    SortingStrategy.IDDesc,
+  SortingStrategy.None,
+  SortingStrategy.AcceptanceRateAsc,
+  SortingStrategy.AcceptanceRateDesc,
+  SortingStrategy.ScoreAsc,
+  SortingStrategy.ScoreDesc,
+  SortingStrategy.IDDesc,
 ];
 
-
 export enum SearchSetType {
-    ScoreRange = "ScoreRange",
-    Context = "Context",
-    Day = "Day",
+  ScoreRange = "ScoreRange",
+  Context = "Context",
+  Day = "Day",
 }
 
 export enum SearchSetTypeName {
-    ScoreRange = "分数范围:",
-    Context = "周赛期数:",
-    Day = "每日一题"
+  ScoreRange = "分数范围:",
+  Context = "周赛期数:",
+  Day = "每日一题",
 }
 
 export interface ISearchSet {
-    value: string,
-    type: SearchSetType,
-    time: number, // 时间戳
-    todayData: ITodayData | undefined;
+  value: string;
+  type: SearchSetType;
+  time: number; // 时间戳
+  todayData: ITodayData | undefined;
 }
 
 export const SearchNode: ISearchSet = {
-    value: "",
-    type: SearchSetType.ScoreRange,
-    time: 0,
-    todayData: undefined
+  value: "",
+  type: SearchSetType.ScoreRange,
+  time: 0,
+  todayData: undefined,
 };
 
 export interface userContestRanKingBase {
-    attendedContestsCount: number, // 参与次数
-    rating: number, // 分数
-    globalRanking: number, // 全球名次
-    localRanking: number, // 本地名次
-    globalTotalParticipants: number, //全球所有
-    localTotalParticipants: number, // 本地所有
-    topPercentage: number, // 位次百分比
+  attendedContestsCount: number; // 参与次数
+  rating: number; // 分数
+  globalRanking: number; // 全球名次
+  localRanking: number; // 本地名次
+  globalTotalParticipants: number; //全球所有
+  localTotalParticipants: number; // 本地所有
+  topPercentage: number; // 位次百分比
 }
 
 export const userContestRankingObj: userContestRanKingBase = {
-    attendedContestsCount: 0,
-    rating: 1500,
-    globalRanking: 0,
-    localRanking: 0,
-    globalTotalParticipants: 0,
-    localTotalParticipants: 0,
-    topPercentage: 0,
+  attendedContestsCount: 0,
+  rating: 1500,
+  globalRanking: 0,
+  localRanking: 0,
+  globalTotalParticipants: 0,
+  localTotalParticipants: 0,
+  topPercentage: 0,
 };
 
-
 export interface ISubmitEvent {
-    fid: string;
-    qid: string;
-    id: string;
-    sub_type: string; // test  submit
-    accepted: boolean
+  fid: string;
+  qid: string;
+  id: string;
+  sub_type: string; // test  submit
+  accepted: boolean;
 }
 
-
 export interface IWebViewOption {
-    title: string;
-    viewColumn: ViewColumn;
-    preserveFocus?: boolean;
+  title: string;
+  viewColumn: ViewColumn;
+  preserveFocus?: boolean;
 }
 
-
 export enum OpenOption {
-    justOpenFile = "仅打开问题文件",
-    openInCurrentWindow = "在当前VsCode窗口打开",
-    openInNewWindow = "在新的VsCode窗口打开",
-    addToWorkspace = "添加到工作空间",
+  justOpenFile = "仅打开问题文件",
+  openInCurrentWindow = "在当前VsCode窗口打开",
+  openInNewWindow = "在新的VsCode窗口打开",
+  addToWorkspace = "添加到工作空间",
 }
 
 export enum DialogType {
-    info = "info",
-    warning = "warning",
-    error = "error",
+  info = "info",
+  warning = "warning",
+  error = "error",
 }
 
-
 export const MessageItemObj: MessageItem = {
-    title: "",
-    isCloseAffordance: false,
+  title: "",
+  isCloseAffordance: false,
 };
 
-
 export const DialogOptions = {
-    open: Object.assign({}, MessageItemObj, { title: "Open" }),
-    yes: Object.assign({}, MessageItemObj, { title: "Yes" }),
-    no: Object.assign({}, MessageItemObj, { title: "No", isCloseAffordance: true }),
-    never: Object.assign({}, MessageItemObj, { title: "Never" }),
-    singUp: Object.assign({}, MessageItemObj, { title: "Sign up" }),
+  open: Object.assign({}, MessageItemObj, { title: "Open" }),
+  yes: Object.assign({}, MessageItemObj, { title: "Yes" }),
+  no: Object.assign({}, MessageItemObj, {
+    title: "No",
+    isCloseAffordance: true,
+  }),
+  never: Object.assign({}, MessageItemObj, { title: "Never" }),
+  singUp: Object.assign({}, MessageItemObj, { title: "Sign up" }),
 };
diff --git a/src/model/NodeModel.ts b/src/model/NodeModel.ts
index 39c0e52..b1b2448 100644
--- a/src/model/NodeModel.ts
+++ b/src/model/NodeModel.ts
@@ -7,137 +7,135 @@
  * Copyright (c) 2022 ccagml . All rights reserved.
  */
 
-
 import { Command, Uri } from "vscode";
 import { IProblem, IScoreData, ITodayData, ProblemState, RootNodeSort } from "./Model";
 
 export class NodeModel {
-    private _u_score;
-    constructor(private data: IProblem, private isProblemNode: boolean = true, userscore: number = 0) {
-        this._u_score = userscore;
-    }
-
-    public get locked(): boolean {
-        return this.data.locked;
-    }
-    public get name(): string {
-        return this.data.name;
-    }
-
-    public get state(): ProblemState {
-
-        // 每日一题的修正
-        if (this.todayData) {
-            const us = this.todayDataUserStatus;
-            if (us == "FINISH") {
-                return ProblemState.AC;
-            } else {
-                return ProblemState.Unknown;
-            }
-        }
-
-        return this.data.state;
-    }
-
-    public get id(): string {
-        return this.data.id;
-    }
-
-    public get passRate(): string {
-        return this.data.passRate;
-    }
-
-    public get difficulty(): string {
-        return this.data.difficulty;
-    }
-
-    public get tags(): string[] {
-        return this.data.tags;
-    }
-
-    public get companies(): string[] {
-        return this.data.companies;
-    }
-
-    public get isFavorite(): boolean {
-        return this.data.isFavorite;
-    }
-
-    public get isProblem(): boolean {
-        return this.isProblemNode;
-    }
-    public get rootNodeSortId(): RootNodeSort {
-        return this.data.rootNodeSortId;
-    }
-
-    public get previewCommand(): Command {
-        return {
-            title: "Preview Problem",
-            command: "leetcode.previewProblem",
-            arguments: [this],
-        };
-    }
-
-    public get acceptanceRate(): number {
-        return Number(this.passRate) || 50;
-    }
-
-    public get uri(): Uri {
-        return Uri.from({
-            scheme: "leetcode",
-            authority: this.isProblem ? "problems" : "tree-node",
-            path: `/${this.id}`, // path must begin with slash /
-            query: `difficulty=${this.difficulty}&score=${this.score}&user_score=${this._u_score}`,
-        });
-    }
-
-    public set set_user_score(s: number) {
-        this._u_score = s;
-    }
-
-    public get user_score(): number {
-        return this._u_score;
-    }
-
-    // rank分
-    public get score(): string {
-        return this.data.scoreData?.score || "0";
-    }
-    // 周赛名称
-    public get ContestID_en(): string {
-        return this.data.scoreData?.ContestID_en || "";
-    }
-    // 周赛第几题
-    public get ProblemIndex(): string {
-        return this.data.scoreData?.ProblemIndex || "";
-    }
-    // 周赛名称符号链接
-    public get ContestSlug(): string {
-        return this.data.scoreData?.ContestSlug || "";
-    }
-    public get scoreData(): IScoreData | undefined {
-        return this.data.scoreData;
-    }
-    public get isSearchResult(): boolean {
-        return this.data.isSearchResult;
-    }
-    public get input(): string {
-        return this.data.input || "";
-    }
-    // 每日一题的一些信息
-    public get todayData(): ITodayData | undefined {
-        return this.data.todayData;
-    }
-    public set todayData(s: ITodayData | undefined) {
-        this.data.todayData = s;
-    }
-    public get todayDataDate(): string {
-        return this.data.todayData?.date || "";
-    }
-    public get todayDataUserStatus(): string {
-        return this.data.todayData?.userStatus || "";
-    }
-    public get qid(): string {
-        return this.data.qid || "";
-    }
+  private _u_score;
+  constructor(private data: IProblem, private isProblemNode: boolean = true, userscore: number = 0) {
+    this._u_score = userscore;
+  }
+
+  public get locked(): boolean {
+    return this.data.locked;
+  }
+  public get name(): string {
+    return this.data.name;
+  }
+
+  public get state(): ProblemState {
+    // 每日一题的修正
+    if (this.todayData) {
+      const us = this.todayDataUserStatus;
+      if (us == "FINISH") {
+        return ProblemState.AC;
+      } else {
+        return ProblemState.Unknown;
+      }
+    }
+
+    return this.data.state;
+  }
+
+  public get id(): string {
+    return this.data.id;
+  }
+
+  public get passRate(): string {
+    return this.data.passRate;
+  }
+
+  public get difficulty(): string {
+    return this.data.difficulty;
+  }
+
+  public get tags(): string[] {
+    return this.data.tags;
+  }
+
+  public get companies(): string[] {
+    return this.data.companies;
+  }
+
+  public get isFavorite(): boolean {
+    return this.data.isFavorite;
+  }
+
+  public get isProblem(): boolean {
+    return this.isProblemNode;
+  }
+  public get rootNodeSortId(): RootNodeSort {
+    return this.data.rootNodeSortId;
+  }
+
+  public get previewCommand(): Command {
+    return {
+      title: "Preview Problem",
+      command: "leetcode.previewProblem",
+      arguments: [this],
+    };
+  }
+
+  public get acceptanceRate(): number {
+    return Number(this.passRate) || 50;
+  }
+
+  public get uri(): Uri {
+    return Uri.from({
+      scheme: "leetcode",
+      authority: this.isProblem ? "problems" : "tree-node",
+      path: `/${this.id}`, // path must begin with slash /
+      query: `difficulty=${this.difficulty}&score=${this.score}&user_score=${this._u_score}`,
+    });
+  }
+
+  public set set_user_score(s: number) {
+    this._u_score = s;
+  }
+
+  public get user_score(): number {
+    return this._u_score;
+  }
+
+  // rank分
+  public get score(): string {
+    return this.data.scoreData?.score || "0";
+  }
+  // 周赛名称
+  public get ContestID_en(): string {
+    return this.data.scoreData?.ContestID_en || "";
+  }
+  // 周赛第几题
+  public get ProblemIndex(): string {
+    return this.data.scoreData?.ProblemIndex || "";
+  }
+  // 周赛名称符号链接
+  public get ContestSlug(): string {
+    return this.data.scoreData?.ContestSlug || "";
+  }
+  public get scoreData(): IScoreData | undefined {
+    return this.data.scoreData;
+  }
+  public get isSearchResult(): boolean {
+    return this.data.isSearchResult;
+  }
+  public get input(): string {
+    return this.data.input || "";
+  }
+  // 每日一题的一些信息
+  public get todayData(): ITodayData | undefined {
+    return this.data.todayData;
+  }
+  public set todayData(s: ITodayData | undefined) {
+    this.data.todayData = s;
+  }
+  public get todayDataDate(): string {
+    return this.data.todayData?.date || "";
+  }
+  public get todayDataUserStatus(): string {
+    return this.data.todayData?.userStatus || "";
+  }
+  public get qid(): string {
+    return this.data.qid || "";
+  }
 }
diff --git a/src/rpc/actionChain/chainManager.ts b/src/rpc/actionChain/chainManager.ts
new file mode 100644
index 0000000..2c0c833
--- /dev/null
+++ b/src/rpc/actionChain/chainManager.ts
@@ -0,0 +1,82 @@
+/*
+ * Filename: /home/cc/vscode-leetcode-problem-rating/src/rpc/actionChain/chainMgr.ts
+ * Path: /home/cc/vscode-leetcode-problem-rating
+ * Created Date: Monday, November 14th 2022, 4:04:31 pm
+ * Author: ccagml
+ *
+ * Copyright (c) 2022 ccagml . All rights reserved.
+ */
+
+let underscore = require("underscore");
+
+import { storageUtils } from "../utils/storageUtils";
+import { commUtils } from "../utils/commUtils";
+import { ChainNodeBase } from "./chainNodeBase";
+
+export class ChainManager {
+  id;
+  name;
+  ver;
+  desc;
+
+  plugins: Array = [];
+  installed: Array = [];
+  head: ChainNodeBase; // 插件头 是core
+
+  constructor() {}
+
+  public getChainHead(): ChainNodeBase {
+    return this.head;
+  }
+
+  public init(head: ChainNodeBase | undefined): Object | undefined {
+    if (head) {
+      this.head = head;
+    }
+    const stats = storageUtils.getCache(commUtils.KEYS.plugins) || {};
+    let fileChainNode: Array = storageUtils.listCodeDir("../actionChain/chainNode");
+    this.installed = [];
+    for (let f of fileChainNode) {
+      const p = f.data;
+      if (!p) continue;
+      p.file = f.file;
+      p.enabled = stats[p.name];
+      if (!(p.name in stats)) {
+        if (p.builtin) {
+          p.enabled = true;
+        } else {
+          p.enabled = false;
+        }
+      }
+      this.installed.push(p);
+    }
+    // 根据id大小排序, 大的前面
+    this.installed = underscore.sortBy(this.installed, (x) => -x.id);
+    // 从小的开始init
+    for (let i = this.installed.length - 1; i >= 0; --i) {
+      const p = this.installed[i];
+      if (p.enabled) {
+        p.init();
+      }
+    }
+    // 连成链表状
+    this.plugins = this.installed.filter((x) => x.enabled);
+    let last = head;
+    if (last) {
+      for (let p of this.plugins) {
+        last.setNext(p);
+        last = p;
+      }
+    }
+
+    return true;
+  }
+
+  public save_all(): void {
+    for (let p of this.plugins) {
+      p.save();
+    }
+  }
+}
+
+export const chainMgr: ChainManager = new ChainManager();
diff --git a/src/rpc/actionChain/chainNode/cache.ts b/src/rpc/actionChain/chainNode/cache.ts
new file mode 100644
index 0000000..05c40e0
--- /dev/null
+++ b/src/rpc/actionChain/chainNode/cache.ts
@@ -0,0 +1,127 @@
+/*
+ * Filename: /home/cc/vscode-leetcode-problem-rating/src/rpc/actionChain/cache.ts
+ * Path: /home/cc/vscode-leetcode-problem-rating
+ * Created Date: Monday, November 14th 2022, 4:04:31 pm
+ * Author: ccagml
+ *
+ * Copyright (c) 2022 ccagml . All rights reserved.
+ */
+
+import { ChainNodeBase } from "../chainNodeBase";
+
+let underscore = require("underscore");
+
+import { storageUtils } from "../../utils/storageUtils";
+import { commUtils } from "../../utils/commUtils";
+import { sessionUtils } from "../../utils/sessionUtils";
+
+class CachePlugin extends ChainNodeBase {
+  id = 50;
+  name = "cache";
+  builtin = true;
+  constructor() {
+    super();
+  }
+
+  clearCacheIfTchanged = (needTranslation) => {
+    const translationConfig = storageUtils.getCache(commUtils.KEYS.translation);
+    if (!translationConfig || translationConfig["useEndpointTranslation"] != needTranslation) {
+      storageUtils.deleteAllCache();
+      storageUtils.setCache(commUtils.KEYS.translation, {
+        useEndpointTranslation: needTranslation,
+      });
+    }
+  };
+
+  public getProblems = (needTranslation, cb) => {
+    this.clearCacheIfTchanged(needTranslation);
+    const problems = storageUtils.getCache(commUtils.KEYS.problems);
+    if (problems) {
+      return cb(null, problems);
+    }
+    this.next.getProblems(needTranslation, function (e, problems) {
+      if (e) return cb(e);
+      storageUtils.setCache(commUtils.KEYS.problems, problems);
+      return cb(null, problems);
+    });
+  };
+
+  /**
+   * getRatingOnline
+   */
+  public getRatingOnline = (cb) => {
+    const cacheRantingData = storageUtils.getCache(commUtils.KEYS.ranting_path);
+    if (cacheRantingData) {
+      return cb(null, cacheRantingData);
+    }
+    this.next.getRatingOnline(function (e, ratingData) {
+      if (e) return cb(e);
+      let ratingObj;
+      try {
+        ratingObj = JSON.parse(ratingData);
+      } catch (error) {
+        return cb("JSON.parse(ratingData) error");
+      }
+      storageUtils.setCache(commUtils.KEYS.ranting_path, ratingObj);
+      return cb(null, ratingObj);
+    });
+  };
+
+  public getProblem = (problem, needTranslation, cb) => {
+    this.clearCacheIfTchanged(needTranslation);
+    const k = commUtils.KEYS.problem(problem);
+    const _problem = storageUtils.getCache(k);
+    let that = this;
+    if (_problem) {
+      if (!_problem.desc.includes("
")) {
+        //
+      } else if (!["likes", "dislikes"].every((p) => p in _problem)) {
+        //
+      } else {
+        underscore.extendOwn(problem, _problem);
+        return cb(null, problem);
+      }
+    }
+    this.next.getProblem(problem, needTranslation, function (e, _problem) {
+      if (e) return cb(e);
+
+      that.saveProblem(_problem);
+      return cb(null, _problem);
+    });
+  };
+
+  saveProblem = (problem) => {
+    const _problem = underscore.omit(problem, ["locked", "state", "starred"]);
+    return storageUtils.setCache(commUtils.KEYS.problem(problem), _problem);
+  };
+
+  updateProblem = (problem, kv) => {
+    const problems = storageUtils.getCache(commUtils.KEYS.problems);
+    if (!problems) return false;
+
+    const _problem = problems.find((x) => x.id === problem.id);
+    if (!_problem) return false;
+
+    underscore.extend(_problem, kv);
+    return storageUtils.setCache(commUtils.KEYS.problems, problems);
+  };
+
+  login = (user, cb) => {
+    this.logout(user, false);
+    this.next.login(user, function (e, user) {
+      if (e) return cb(e);
+      sessionUtils.saveUser(user);
+      return cb(null, user);
+    });
+  };
+
+  logout = (user, purge) => {
+    if (!user) user = sessionUtils.getUser();
+    if (purge) sessionUtils.deleteUser();
+    // NOTE: need invalidate any user related cache
+    sessionUtils.deleteCodingSession();
+    return user;
+  };
+}
+
+export const pluginObj: CachePlugin = new CachePlugin();
diff --git a/src/childProcessCall/core.ts b/src/rpc/actionChain/chainNode/core.ts
similarity index 53%
rename from src/childProcessCall/core.ts
rename to src/rpc/actionChain/chainNode/core.ts
index 2fb9aa9..1767685 100644
--- a/src/childProcessCall/core.ts
+++ b/src/rpc/actionChain/chainNode/core.ts
@@ -1,76 +1,47 @@
 /*
- * Filename: https://github.com/ccagml/vscode-leetcode-problem-rating/src/childProcessCall/core.ts
- * Path: https://github.com/ccagml/vscode-leetcode-problem-rating
- * Created Date: Thursday, October 27th 2022, 7:43:29 pm
+ * Filename: /home/cc/vscode-leetcode-problem-rating/src/rpc/actionChain/core.ts
+ * Path: /home/cc/vscode-leetcode-problem-rating
+ * Created Date: Monday, November 14th 2022, 4:04:31 pm
  * Author: ccagml
  *
  * Copyright (c) 2022 ccagml . All rights reserved.
  */
 
+let util = require("util");
 
-let util = require('util');
+let _ = require("underscore");
+let cheerio = require("cheerio");
 
-let _ = require('underscore');
-let cheerio = require('cheerio');
+import { storageUtils } from "../../utils/storageUtils";
+import { configUtils } from "../../utils/configUtils";
 
-// import { log } from "./log";
-import { helper } from "./helper";
-import { storageUtils } from "./storageUtils";
-
-import { MyPluginBase } from "./my_plugin_base";
+import { ChainNodeBase } from "../chainNodeBase";
 
 function hasTag(o, tag) {
-  return Array.isArray(o) && o.some(x => x.indexOf(tag.toLowerCase()) >= 0);
+  return Array.isArray(o) && o.some((x) => x.indexOf(tag.toLowerCase()) >= 0);
 }
 
-class CorePlugin extends MyPluginBase {
+class CorePlugin extends ChainNodeBase {
   id = 99999999;
-  name = 'core';
+  name = "core";
   builtin = true;
-  filters = {
-    query: {
-      alias: 'query',
-      type: 'string',
-      default: '',
-      describe: [
-        'Filter questions by condition:',
-        'Uppercase means negative',
-        'e = easy     E = m+h',
-        'm = medium   M = e+h',
-        'h = hard     H = e+m',
-        'd = done     D = not done',
-        'l = locked   L = non locked',
-        's = starred  S = not starred'
-      ].join('\n')
-    },
-    tag: {
-      alias: 'tag',
-      type: 'array',
-      default: [],
-      describe: 'Filter questions by tag'
-    }
-  };
-
   constructor() {
     super();
   }
 
-
   filterProblems = (opts, cb) => {
     this.getProblems(!opts.dontTranslate, function (e, problems) {
       if (e) return cb(e);
 
-      for (let q of (opts.query || '').split('')) {
+      for (let q of (opts.query || "").split("")) {
         const f = QUERY_HANDLERS[q];
         if (!f) continue;
-        problems = problems.filter(x => f(x, q));
+        problems = problems.filter((x) => f(x, q));
       }
 
-      for (let t of (opts.tag || [])) {
+      for (let t of opts.tag || []) {
         problems = problems.filter(function (x) {
-          return x.category === t ||
-            hasTag(x.companies, t) ||
-            hasTag(x.tags, t);
+          return x.category === t || hasTag(x.companies, t) || hasTag(x.tags, t);
         });
       }
 
@@ -85,21 +56,20 @@ class CorePlugin extends MyPluginBase {
       const metaFid = storageUtils.exist(keyword) ? storageUtils.meta(keyword).id : NaN;
       const problem = problems.find(function (x) {
         if (keyword?.fid) {
-          return x.fid + '' === keyword.fid + '';
+          return x.fid + "" === keyword.fid + "";
         } else if (keyword?.qid) {
-          return x.id + '' === keyword.qid + '';
+          return x.id + "" === keyword.qid + "";
         } else {
-          return x.id + '' === keyword + '' || x.fid + '' === metaFid + '' || x.name === keyword || x.slug === keyword;
+          return x.id + "" === keyword + "" || x.fid + "" === metaFid + "" || x.name === keyword || x.slug === keyword;
         }
       });
-      if (!problem) return cb('Problem not found!');
+      if (!problem) return cb("Problem not found!");
       that.next.getProblem(problem, needTranslation, cb);
     });
   };
 
   starProblem = (problem, starred, cb) => {
     if (problem.starred === starred) {
-
       return cb(null, starred);
     }
 
@@ -109,26 +79,29 @@ class CorePlugin extends MyPluginBase {
   exportProblem = (problem, opts) => {
     const data = _.extend({}, problem);
 
+    // 增加版本信息
+    data.LCPTCTX = configUtils.LCPTCTX;
+    data.allCaseList = storageUtils.getAllCase(problem.desc);
     // unify format before rendering
 
-    data.app = require('./config').app || 'leetcode';
+    data.app = configUtils.app || "leetcode";
     if (!data.fid) data.fid = data.id;
     if (!data.lang) data.lang = opts.lang;
-    data.code = (opts.code || data.code || '').replace(/\r\n/g, '\n');
-    data.comment = helper.langToCommentStyle(data.lang);
+    data.code = (opts.code || data.code || "").replace(/\r\n/g, "\n");
+    data.comment = storageUtils.getCommentStyleByLanguage(data.lang);
     data.percent = data.percent.toFixed(2);
-    data.testcase = util.inspect(data.testcase || '');
+    data.testcase = util.inspect(data.testcase || "");
 
-    if (opts.tpl === 'detailed') {
+    if (opts.tpl === "detailed") {
       let desc = data.desc;
       // Replace  with '^' as the power operator
-      desc = desc.replace(/<\/sup>/gm, '').replace(//gm, '^');
-      desc = require('he').decode(cheerio.load(desc).root().text());
+      desc = desc.replace(/<\/sup>/gm, "").replace(//gm, "^");
+      desc = require("he").decode(cheerio.load(desc).root().text());
       // NOTE: wordwrap internally uses '\n' as EOL, so here we have to
       // remove all '\r' in the raw string.
-      desc = desc.replace(/\r\n/g, '\n').replace(/^ /mg, '⁠');
-      const wrap = require('wordwrap')(79 - data.comment.line.length);
-      data.desc = wrap(desc).split('\n');
+      desc = desc.replace(/\r\n/g, "\n").replace(/^ /gm, "⁠");
+      const wrap = require("wordwrap")(79 - data.comment.line.length);
+      data.desc = wrap(desc).split("\n");
     }
     return storageUtils.render(opts.tpl, data);
   };
@@ -162,11 +135,10 @@ class CorePlugin extends MyPluginBase {
   };
 }
 
-
 const isLevel = (x, q) => x.level[0].toLowerCase() === q.toLowerCase();
-const isACed = x => x.state === 'ac';
-const isLocked = x => x.locked;
-const isStarred = x => x.starred;
+const isACed = (x) => x.state === "ac";
+const isLocked = (x) => x.locked;
+const isStarred = (x) => x.starred;
 
 const QUERY_HANDLERS = {
   e: isLevel,
@@ -180,7 +152,7 @@ const QUERY_HANDLERS = {
   d: isACed,
   D: _.negate(isACed),
   s: isStarred,
-  S: _.negate(isStarred)
+  S: _.negate(isStarred),
 };
 
 export const corePlugin: CorePlugin = new CorePlugin();
diff --git a/src/childProcessCall/plugins/leetcode.cn.ts b/src/rpc/actionChain/chainNode/leetcode.cn.ts
similarity index 53%
rename from src/childProcessCall/plugins/leetcode.cn.ts
rename to src/rpc/actionChain/chainNode/leetcode.cn.ts
index 1137db9..958cd0e 100644
--- a/src/childProcessCall/plugins/leetcode.cn.ts
+++ b/src/rpc/actionChain/chainNode/leetcode.cn.ts
@@ -1,31 +1,30 @@
 /*
- * Filename: https://github.com/ccagml/vscode-leetcode-problem-rating/src/childProcessCall/plugins/leetcode.cn.ts
- * Path: https://github.com/ccagml/vscode-leetcode-problem-rating
- * Created Date: Thursday, October 27th 2022, 7:43:29 pm
+ * Filename: /home/cc/vscode-leetcode-problem-rating/src/rpc/actionChain/leetcode.cn.ts
+ * Path: /home/cc/vscode-leetcode-problem-rating
+ * Created Date: Monday, November 14th 2022, 4:04:31 pm
  * Author: ccagml
  *
  * Copyright (c) 2022 ccagml . All rights reserved.
  */
 
+import { ChainNodeBase } from "../chainNodeBase";
 
-import { MyPluginBase } from "../my_plugin_base";
+let request = require("request");
 
-let request = require('request');
+import { configUtils } from "../../utils/configUtils";
 
-import { config } from "../config";
+import { sessionUtils } from "../../utils/sessionUtils";
 
-import { session } from "../session";
-
-class LeetCodeCn extends MyPluginBase {
+class LeetCodeCn extends ChainNodeBase {
   id = 15;
-  name = 'leetcode.cn';
+  name = "leetcode.cn";
   builtin = true;
   constructor() {
     super();
   }
   init() {
-    config.fix_cn();
-  };
+    configUtils.fix_cn();
+  }
 
   getProblems = (needTranslation, cb) => {
     let that = this;
@@ -39,8 +38,7 @@ class LeetCodeCn extends MyPluginBase {
 
           problems.forEach(function (problem) {
             const title = titles[problem.id];
-            if (title)
-              problem.name = title;
+            if (title) problem.name = title;
           });
 
           return cb(null, problems);
@@ -52,29 +50,26 @@ class LeetCodeCn extends MyPluginBase {
   };
 
   getProblemsTitle = (cb) => {
-
-    const opts = makeOpts(config.sys.urls.graphql);
-    opts.headers.Origin = config.sys.urls.base;
-    opts.headers.Referer = 'https://leetcode.cn/api/problems/algorithms/';
+    const opts = makeOpts(configUtils.sys.urls.graphql);
+    opts.headers.Origin = configUtils.sys.urls.base;
+    opts.headers.Referer = "https://leetcode.cn/api/problems/algorithms/";
 
     opts.json = true;
     opts.body = {
       query: [
-        'query getQuestionTranslation($lang: String) {',
-        '  translations: allAppliedQuestionTranslations(lang: $lang) {',
-        '    title',
-        '    questionId',
-        '    __typename',
-        '    }',
-        '}'
-      ].join('\n'),
+        "query getQuestionTranslation($lang: String) {",
+        "  translations: allAppliedQuestionTranslations(lang: $lang) {",
+        "    title",
+        "    questionId",
+        "    __typename",
+        "    }",
+        "}",
+      ].join("\n"),
       variables: {},
-      operationName: 'getQuestionTranslation'
+      operationName: "getQuestionTranslation",
     };
 
-
     request.post(opts, function (e, resp, body) {
-
       e = checkError(e, resp, 200);
       if (e) return cb(e);
 
@@ -88,24 +83,23 @@ class LeetCodeCn extends MyPluginBase {
   };
 
   getQuestionOfToday = (cb) => {
-
-    const opts = makeOpts(config.sys.urls.graphql);
-    opts.headers.Origin = config.sys.urls.base;
-    opts.headers.Referer = 'https://leetcode.cn/';
+    const opts = makeOpts(configUtils.sys.urls.graphql);
+    opts.headers.Origin = configUtils.sys.urls.base;
+    opts.headers.Referer = "https://leetcode.cn/";
 
     opts.json = true;
     opts.body = {
       operationName: "questionOfToday",
       variables: {},
       query: [
-        'query questionOfToday {',
-        '  todayRecord {',
-        '    date',
-        '    userStatus',
-        '    question {',
-        '      titleSlug',
-        '      questionId',
-        '      questionFrontendId',
+        "query questionOfToday {",
+        "  todayRecord {",
+        "    date",
+        "    userStatus",
+        "    question {",
+        "      titleSlug",
+        "      questionId",
+        "      questionFrontendId",
         // '      content',
         // '      stats',
         // '      likes',
@@ -115,17 +109,15 @@ class LeetCodeCn extends MyPluginBase {
         // '      enableRunCode',
         // '      metaData',
         // '      translatedContent',
-        '      __typename',
-        '    }',
-        '  __typename',
-        '  }',
-        '}'
-      ].join('\n'),
+        "      __typename",
+        "    }",
+        "  __typename",
+        "  }",
+        "}",
+      ].join("\n"),
     };
 
-
     request.post(opts, function (e, resp, body) {
-
       e = checkError(e, resp, 200);
       if (e) return cb(e);
       let result: any = {};
@@ -138,27 +130,26 @@ class LeetCodeCn extends MyPluginBase {
     });
   };
   getUserContestP = (username, cb) => {
-
-    const opts = makeOpts(config.sys.urls.noj_go);
-    opts.headers.Origin = config.sys.urls.base;
-    opts.headers.Referer = config.sys.urls.u.replace('$username', username);
+    const opts = makeOpts(configUtils.sys.urls.noj_go);
+    opts.headers.Origin = configUtils.sys.urls.base;
+    opts.headers.Referer = configUtils.sys.urls.u.replace("$username", username);
 
     opts.json = true;
     opts.body = {
       variables: {
-        userSlug: username
+        userSlug: username,
       },
       query: [
-        '        query userContestRankingInfo($userSlug: String!) {',
-        '          userContestRanking(userSlug: $userSlug) {',
-        '            attendedContestsCount',
-        '            rating',
-        '            globalRanking',
-        '            localRanking',
-        '            globalTotalParticipants',
-        '            localTotalParticipants',
-        '            topPercentage',
-        '        }',
+        "        query userContestRankingInfo($userSlug: String!) {",
+        "          userContestRanking(userSlug: $userSlug) {",
+        "            attendedContestsCount",
+        "            rating",
+        "            globalRanking",
+        "            localRanking",
+        "            globalTotalParticipants",
+        "            localTotalParticipants",
+        "            topPercentage",
+        "        }",
         // '      userContestRankingHistory(userSlug: $userSlug) {',
         // '            attended',
         // '            totalProblems',
@@ -173,13 +164,11 @@ class LeetCodeCn extends MyPluginBase {
         // '              startTime',
         // '            }',
         // '        }',
-        '    }'
-      ].join('\n'),
+        "    }",
+      ].join("\n"),
     };
 
-
     request.post(opts, function (e, resp, body) {
-
       e = checkError(e, resp, 200);
       if (e) return cb(e);
 
@@ -187,55 +176,53 @@ class LeetCodeCn extends MyPluginBase {
     });
   };
 
-
   getRatingOnline = (cb) => {
     const _request = request.defaults({ jar: true });
-    _request("https://zerotrac.github.io/leetcode_problem_rating/data.json", function (error, _, body) {
+    _request("https://zerotrac.github.io/leetcode_problem_rating/data.json", function (error: any, _, body: any) {
       // console.log(error);
       // console.log(info);
       cb(error, body);
     });
   };
 
-
-  getTestApi = (value, _) => {
+  // eslint-disable-next-line @typescript-eslint/no-unused-vars
+  getTestApi = (value: any, _) => {
     const _request = request.defaults({ jar: true });
-    _request("https://zerotrac.github.io/leetcode_problem_rating/data.json", function (error, info, body) {
-      console.log(error);
-      console.log(info);
-      let a = body;
-      console.log(a, value);
-    });
+    _request(
+      "https://zerotrac.github.io/leetcode_problem_rating/data.json",
+      function (error: any, info: any, body: any) {
+        console.log(error);
+        console.log(info);
+        let a = body;
+        console.log(a, value);
+      }
+    );
   };
 }
 
-
-function signOpts(opts, user) {
-  opts.headers.Cookie = 'LEETCODE_SESSION=' + user.sessionId +
-    ';csrftoken=' + user.sessionCSRF + ';';
-  opts.headers['X-CSRFToken'] = user.sessionCSRF;
-  opts.headers['X-Requested-With'] = 'XMLHttpRequest';
+function signOpts(opts: any, user: any) {
+  opts.headers.Cookie = "LEETCODE_SESSION=" + user.sessionId + ";csrftoken=" + user.sessionCSRF + ";";
+  opts.headers["X-CSRFToken"] = user.sessionCSRF;
+  opts.headers["X-Requested-With"] = "XMLHttpRequest";
 }
 
-function makeOpts(url) {
+function makeOpts(url: any) {
   let opts: any = {};
   opts.url = url;
   opts.headers = {};
 
-  if (session.isLogin())
-    signOpts(opts, session.getUser());
+  if (sessionUtils.isLogin()) signOpts(opts, sessionUtils.getUser());
   return opts;
 }
 
-function checkError(e, resp, expectedStatus) {
+function checkError(e: any, resp: any, expectedStatus: any) {
   if (!e && resp && resp.statusCode !== expectedStatus) {
     const code = resp.statusCode;
 
-
     if (code === 403 || code === 401) {
-      e = session.errors.EXPIRED;
+      e = sessionUtils.errors.EXPIRED;
     } else {
-      e = { msg: 'http error', statusCode: code };
+      e = { msg: "http error", statusCode: code };
     }
   }
   return e;
diff --git a/src/childProcessCall/plugins/leetcode.ts b/src/rpc/actionChain/chainNode/leetcode.ts
similarity index 55%
rename from src/childProcessCall/plugins/leetcode.ts
rename to src/rpc/actionChain/chainNode/leetcode.ts
index bfaa5d9..c5e4084 100644
--- a/src/childProcessCall/plugins/leetcode.ts
+++ b/src/rpc/actionChain/chainNode/leetcode.ts
@@ -1,69 +1,65 @@
 /*
- * Filename: https://github.com/ccagml/vscode-leetcode-problem-rating/src/childProcessCall/plugins/leetcode.ts
- * Path: https://github.com/ccagml/vscode-leetcode-problem-rating
- * Created Date: Thursday, October 27th 2022, 7:43:29 pm
+ * Filename: /home/cc/vscode-leetcode-problem-rating/src/rpc/actionChain/leetcode.ts
+ * Path: /home/cc/vscode-leetcode-problem-rating
+ * Created Date: Monday, November 14th 2022, 4:04:31 pm
  * Author: ccagml
  *
  * Copyright (c) 2022 ccagml . All rights reserved.
  */
 
+let util = require("util");
 
+let underscore = require("underscore");
+let request = require("request");
+let prompt_out = require("prompt");
 
-let util = require('util');
+import { configUtils } from "../../utils/configUtils";
+import { commUtils } from "../../utils/commUtils";
+import { storageUtils } from "../../utils/storageUtils";
+import { reply } from "../../utils/ReplyUtils";
+import { sessionUtils } from "../../utils/sessionUtils";
+import { ChainNodeBase } from "../chainNodeBase";
+import { Queue } from "../../utils/queueUtils";
 
-let underscore = require('underscore');
-let request = require('request');
-let prompt_out = require('prompt');
-
-import { config } from "../config";
-import { helper } from "../helper";
-import { storageUtils } from "../storageUtils";
-import { log } from "../log";
-import { session } from "../session";
-import { MyPluginBase } from "../my_plugin_base";
-import { Queue } from "../queue";
-
-class LeetCode extends MyPluginBase {
+class LeetCode extends ChainNodeBase {
   id = 10;
-  name = 'leetcode';
+  name = "leetcode";
   builtin = true;
   constructor() {
     super();
   }
 
   signOpts(opts, user) {
-    opts.headers.Cookie = 'LEETCODE_SESSION=' + user.sessionId +
-      ';csrftoken=' + user.sessionCSRF + ';';
-    opts.headers['X-CSRFToken'] = user.sessionCSRF;
-    opts.headers['X-Requested-With'] = 'XMLHttpRequest';
-  };
+    opts.headers.Cookie = "LEETCODE_SESSION=" + user.sessionId + ";csrftoken=" + user.sessionCSRF + ";";
+    opts.headers["X-CSRFToken"] = user.sessionCSRF;
+    opts.headers["X-Requested-With"] = "XMLHttpRequest";
+  }
 
   makeOpts(url) {
     const opts: any = {};
     opts.url = url;
     opts.headers = {};
 
-    if (session.isLogin())
-      this.signOpts(opts, session.getUser());
+    if (sessionUtils.isLogin()) this.signOpts(opts, sessionUtils.getUser());
     return opts;
-  };
+  }
 
   checkError(e, resp, expectedStatus) {
     if (!e && resp && resp.statusCode !== expectedStatus) {
       const code = resp.statusCode;
 
       if (code === 403 || code === 401) {
-        e = session.errors.EXPIRED;
+        e = sessionUtils.errors.EXPIRED;
       } else {
-        e = { msg: 'http error', statusCode: code };
+        e = { msg: "http error", statusCode: code };
       }
     }
     return e;
-  };
+  }
 
   init() {
-    config.app = 'leetcode';
-  };
+    configUtils.app = "leetcode";
+  }
 
   getProblems = (_, cb) => {
     let that = this;
@@ -73,24 +69,20 @@ class LeetCode extends MyPluginBase {
         if (e) {
           //
         } else {
-
           problems = problems.concat(_problems);
         }
         return cb(e);
       });
     };
 
-
-    const q = new Queue(config.sys.categories, {}, getCategory);
+    const q = new Queue(configUtils.sys.categories, {}, getCategory);
     q.run(null, function (e) {
-
       return cb(e, problems);
     });
   };
 
   getCategoryProblems = (category, cb) => {
-
-    const opts = this.makeOpts(config.sys.urls.problems.replace('$category', category));
+    const opts = this.makeOpts(configUtils.sys.urls.problems.replace("$category", category));
 
     let that = this;
     request(opts, function (e, resp, body) {
@@ -99,27 +91,25 @@ class LeetCode extends MyPluginBase {
 
       const json = JSON.parse(body);
 
-
       if (json.user_name.length === 0) {
-
-        return cb(session.errors.EXPIRED);
+        return cb(sessionUtils.errors.EXPIRED);
       }
 
       const problems = json.stat_status_pairs
         .filter((p) => !p.stat.question__hide)
         .map(function (p) {
           return {
-            state: p.status || 'None',
+            state: p.status || "None",
             id: p.stat.question_id,
             fid: p.stat.frontend_question_id,
             name: p.stat.question__title,
             slug: p.stat.question__title_slug,
-            link: config.sys.urls.problem.replace('$slug', p.stat.question__title_slug),
+            link: configUtils.sys.urls.problem.replace("$slug", p.stat.question__title_slug),
             locked: p.paid_only,
-            percent: p.stat.total_acs * 100 / p.stat.total_submitted,
-            level: helper.levelToName(p.difficulty.level),
+            percent: (p.stat.total_acs * 100) / p.stat.total_submitted,
+            level: commUtils.getNameByLevel(p.difficulty.level),
             starred: p.is_favor,
-            category: json.category_slug
+            category: json.category_slug,
           };
         });
 
@@ -128,51 +118,48 @@ class LeetCode extends MyPluginBase {
   };
 
   getProblem = (problem, needTranslation, cb) => {
+    const user = sessionUtils.getUser();
+    if (problem.locked && !user.paid) return cb("failed to load locked problem!");
 
-    const user = session.getUser();
-    if (problem.locked && !user.paid) return cb('failed to load locked problem!');
-
-    const opts = this.makeOpts(config.sys.urls.graphql);
-    opts.headers.Origin = config.sys.urls.base;
+    const opts = this.makeOpts(configUtils.sys.urls.graphql);
+    opts.headers.Origin = configUtils.sys.urls.base;
     opts.headers.Referer = problem.link;
 
     opts.json = true;
     opts.body = {
       query: [
-        'query getQuestionDetail($titleSlug: String!) {',
-        '  question(titleSlug: $titleSlug) {',
-        '    content',
-        '    stats',
-        '    likes',
-        '    dislikes',
-        '    codeDefinition',
-        '    sampleTestCase',
-        '    enableRunCode',
-        '    metaData',
-        '    translatedContent',
-        '  }',
-        '}'
-      ].join('\n'),
+        "query getQuestionDetail($titleSlug: String!) {",
+        "  question(titleSlug: $titleSlug) {",
+        "    content",
+        "    stats",
+        "    likes",
+        "    dislikes",
+        "    codeDefinition",
+        "    sampleTestCase",
+        "    enableRunCode",
+        "    metaData",
+        "    translatedContent",
+        "  }",
+        "}",
+      ].join("\n"),
       variables: { titleSlug: problem.slug },
-      operationName: 'getQuestionDetail'
+      operationName: "getQuestionDetail",
     };
 
-
     let that = this;
     request.post(opts, function (e, resp, body) {
-
       e = that.checkError(e, resp, 200);
       if (e) return cb(e);
 
       const q = body.data.question;
-      if (!q) return cb('failed to load problem!');
+      if (!q) return cb("failed to load problem!");
 
       problem.totalAC = JSON.parse(q.stats).totalAccepted;
       problem.totalSubmit = JSON.parse(q.stats).totalSubmission;
       problem.likes = q.likes;
       problem.dislikes = q.dislikes;
 
-      problem.desc = (q.translatedContent && needTranslation) ? q.translatedContent : q.content;
+      problem.desc = q.translatedContent && needTranslation ? q.translatedContent : q.content;
 
       problem.templates = JSON.parse(q.codeDefinition);
       problem.testcase = q.sampleTestCase;
@@ -185,31 +172,27 @@ class LeetCode extends MyPluginBase {
     });
   };
   runCode = (opts, problem, cb) => {
-    opts.method = 'POST';
-    opts.headers.Origin = config.sys.urls.base;
+    opts.method = "POST";
+    opts.headers.Origin = configUtils.sys.urls.base;
     opts.headers.Referer = problem.link;
     opts.json = true;
-    opts._delay = opts._delay || config.network.delay || 1; // in seconds
+    opts._delay = opts._delay || configUtils.network.delay || 1; // in seconds
 
     opts.body = opts.body || {};
     underscore.extendOwn(opts.body, {
       lang: problem.lang,
       question_id: parseInt(problem.id, 10),
       test_mode: false,
-      typed_code: storageUtils.codeData(problem.file)
+      typed_code: storageUtils.codeData(problem.file),
     });
 
-
     let that = this;
     request(opts, function (e, resp, body) {
-
       e = that.checkError(e, resp, 200);
       if (e) return cb(e);
 
       if (body.error) {
-        if (!body.error.includes('too soon'))
-          return cb(body.error);
-
+        if (!body.error.includes("too soon")) return cb(body.error);
 
         ++opts._delay;
 
@@ -224,21 +207,18 @@ class LeetCode extends MyPluginBase {
     });
   };
 
-
   verifyResult = (task, queue, cb) => {
     const opts = queue.ctx.opts;
-    opts.method = 'GET';
-    opts.url = config.sys.urls.verify.replace('$id', task.id);
-
+    opts.method = "GET";
+    opts.url = configUtils.sys.urls.verify.replace("$id", task.id);
 
     let that = this;
     request(opts, function (e, resp, body) {
-
       e = that.checkError(e, resp, 200);
       if (e) return cb(e);
 
       let result = JSON.parse(body);
-      if (result.state === 'SUCCESS') {
+      if (result.state === "SUCCESS") {
         result = that.formatResult(result);
         underscore.extendOwn(result, task);
         queue.ctx.results.push(result);
@@ -253,17 +233,18 @@ class LeetCode extends MyPluginBase {
     const x: any = {
       ok: result.run_success,
       lang: result.lang,
-      runtime: result.status_runtime || '',
-      runtime_percentile: result.runtime_percentile || '',
-      memory: result.status_memory || '',
-      memory_percentile: result.memory_percentile || '',
+      runtime: result.status_runtime || "",
+      runtime_percentile: result.runtime_percentile || "",
+      memory: result.status_memory || "",
+      memory_percentile: result.memory_percentile || "",
       state: result.status_msg,
-      testcase: util.inspect(result.input || result.last_testcase || ''),
+      testcase: util.inspect(result.input || result.last_testcase || ""),
       passed: result.total_correct || 0,
-      total: result.total_testcases || 0
+      total: result.total_testcases || 0,
     };
 
-    x.error = underscore.chain(result)
+    x.error = underscore
+      .chain(result)
       .pick((v, k) => /_error$/.test(k) && v.length > 0)
       .values()
       .value();
@@ -272,7 +253,7 @@ class LeetCode extends MyPluginBase {
       // It's testing
       let output = result.code_output || [];
       if (Array.isArray(output)) {
-        output = output.join('\n');
+        output = output.join("\n");
       }
       x.stdout = util.inspect(output);
       x.answer = result.code_answer;
@@ -287,27 +268,24 @@ class LeetCode extends MyPluginBase {
 
     // make sure we pass eveything!
     if (x.passed !== x.total) x.ok = false;
-    if (x.state !== 'Accepted') x.ok = false;
+    if (x.state !== "Accepted") x.ok = false;
     if (x.error.length > 0) x.ok = false;
 
     return x;
   };
 
   testProblem = (problem, cb) => {
-
-    const opts = this.makeOpts(config.sys.urls.test.replace('$slug', problem.slug));
+    const opts = this.makeOpts(configUtils.sys.urls.test.replace("$slug", problem.slug));
     opts.body = { data_input: problem.testcase };
     let that = this;
     this.runCode(opts, problem, function (e, task) {
       if (e) return cb(e);
 
-      const tasks = [
-        { type: 'Actual', id: task.interpret_id },
-      ];
+      const tasks = [{ type: "Actual", id: task.interpret_id }];
 
       // Used by LeetCode-CN
       if (task.interpret_expected_id) {
-        tasks.push({ type: 'Expected', id: task.interpret_expected_id });
+        tasks.push({ type: "Expected", id: task.interpret_expected_id });
       }
       const q = new Queue(tasks, { opts: opts, results: [] }, that.verifyResult);
       q.run(null, function (e, ctx) {
@@ -317,14 +295,13 @@ class LeetCode extends MyPluginBase {
   };
 
   submitProblem = (problem, cb) => {
-
-    const opts = this.makeOpts(config.sys.urls.submit.replace('$slug', problem.slug));
-    opts.body = { judge_type: 'large' };
+    const opts = this.makeOpts(configUtils.sys.urls.submit.replace("$slug", problem.slug));
+    opts.body = { judge_type: "large" };
     let that = this;
     this.runCode(opts, problem, function (e, task) {
       if (e) return cb(e);
 
-      const tasks = [{ type: 'Actual', id: task.submission_id }];
+      const tasks = [{ type: "Actual", id: task.submission_id }];
       const q = new Queue(tasks, { opts: opts, results: [] }, that.verifyResult);
       q.run(null, function (e, ctx) {
         return cb(e, ctx.results);
@@ -333,9 +310,8 @@ class LeetCode extends MyPluginBase {
   };
 
   getSubmissions = (problem, cb) => {
-
-    const opts = this.makeOpts(config.sys.urls.submissions.replace('$slug', problem.slug));
-    opts.headers.Referer = config.sys.urls.problem.replace('$slug', problem.slug);
+    const opts = this.makeOpts(configUtils.sys.urls.submissions.replace("$slug", problem.slug));
+    opts.headers.Referer = configUtils.sys.urls.problem.replace("$slug", problem.slug);
     let that = this;
     request(opts, function (e, resp, body) {
       e = that.checkError(e, resp, 200);
@@ -344,15 +320,14 @@ class LeetCode extends MyPluginBase {
       // FIXME: this only return the 1st 20 submissions, we should get next if necessary.
       const submissions = JSON.parse(body).submissions_dump;
       for (const submission of submissions)
-        submission.id = underscore.last(underscore.compact(submission.url.split('/')));
+        submission.id = underscore.last(underscore.compact(submission.url.split("/")));
 
       return cb(null, submissions);
     });
   };
 
   getSubmission = (submission, cb) => {
-
-    const opts = this.makeOpts(config.sys.urls.submission.replace('$id', submission.id));
+    const opts = this.makeOpts(configUtils.sys.urls.submission.replace("$id", submission.id));
     let that = this;
     request(opts, function (e, resp, body) {
       e = that.checkError(e, resp, 200);
@@ -368,38 +343,33 @@ class LeetCode extends MyPluginBase {
   };
 
   starProblem = (problem, starred, cb) => {
-
-    const user = session.getUser();
-    const operationName = starred ? 'addQuestionToFavorite' : 'removeQuestionFromFavorite';
-    const opts = this.makeOpts(config.sys.urls.graphql);
-    opts.headers.Origin = config.sys.urls.base;
+    const user = sessionUtils.getUser();
+    const operationName = starred ? "addQuestionToFavorite" : "removeQuestionFromFavorite";
+    const opts = this.makeOpts(configUtils.sys.urls.graphql);
+    opts.headers.Origin = configUtils.sys.urls.base;
     opts.headers.Referer = problem.link;
 
     opts.json = true;
     opts.body = {
       query: `mutation ${operationName}($favoriteIdHash: String!, $questionId: String!) {\n  ${operationName}(favoriteIdHash: $favoriteIdHash, questionId: $questionId) {\n    ok\n    error\n    favoriteIdHash\n    questionId\n    __typename\n  }\n}\n`,
-      variables: { favoriteIdHash: user.hash, questionId: '' + problem.id },
-      operationName: operationName
+      variables: { favoriteIdHash: user.hash, questionId: "" + problem.id },
+      operationName: operationName,
     };
 
-
     let that = this;
-    request.post(opts, function (e, resp, _) {
-
+    // eslint-disable-next-line @typescript-eslint/no-unused-vars
+    request.post(opts, function (e: any, resp: any, _) {
       e = that.checkError(e, resp, 200);
       if (e) return cb(e);
       return cb(null, starred);
     });
   };
 
-  getFavorites = (cb) => {
-
-    const opts = this.makeOpts(config.sys.urls.favorites);
-
+  getFavorites = (cb: any) => {
+    const opts = this.makeOpts(configUtils.sys.urls.favorites);
 
     let that = this;
     request(opts, function (e, resp, body) {
-
       e = that.checkError(e, resp, 200);
       if (e) return cb(e);
 
@@ -408,27 +378,18 @@ class LeetCode extends MyPluginBase {
     });
   };
 
-  getUserInfo = (cb) => {
+  getUserInfo = (cb: any) => {
     let that = this;
-    const opts = this.makeOpts(config.sys.urls.graphql);
-    opts.headers.Origin = config.sys.urls.base;
-    opts.headers.Referer = config.sys.urls.base;
+    const opts = this.makeOpts(configUtils.sys.urls.graphql);
+    opts.headers.Origin = configUtils.sys.urls.base;
+    opts.headers.Referer = configUtils.sys.urls.base;
     opts.json = true;
     opts.body = {
-      query: [
-        '{',
-        '  user {',
-        '    username',
-        '    isCurrentUserPremium',
-        '  }',
-        '}'
-      ].join('\n'),
-      variables: {}
+      query: ["{", "  user {", "    username", "    isCurrentUserPremium", "  }", "}"].join("\n"),
+      variables: {},
     };
 
-
     request.post(opts, function (e, resp, body) {
-
       e = that.checkError(e, resp, 200);
       if (e) return cb(e);
 
@@ -437,77 +398,68 @@ class LeetCode extends MyPluginBase {
     });
   };
 
-
-  runSession = (method, data, cb) => {
-    const opts = this.makeOpts(config.sys.urls.session);
+  runSession = (method: any, data: any, cb: any) => {
+    const opts = this.makeOpts(configUtils.sys.urls.session);
     opts.json = true;
     opts.method = method;
     opts.body = data;
 
-
     let that = this;
     request(opts, function (e, resp, body) {
-
       e = that.checkError(e, resp, 200);
-      if (e && e.statusCode === 302) e = session.errors.EXPIRED;
+      if (e && e.statusCode === 302) e = sessionUtils.errors.EXPIRED;
 
       return e ? cb(e) : cb(null, body.sessions);
     });
   };
 
   getSessions = (cb) => {
-
-    this.runSession('POST', {}, cb);
+    this.runSession("POST", {}, cb);
   };
 
   activateSession = (session, cb) => {
-    const data = { func: 'activate', target: session.id };
-    this.runSession('PUT', data, cb);
+    const data = { func: "activate", target: session.id };
+    this.runSession("PUT", data, cb);
   };
 
   createSession = (name, cb) => {
-
-    const data = { func: 'create', name: name };
-    this.runSession('PUT', data, cb);
+    const data = { func: "create", name: name };
+    this.runSession("PUT", data, cb);
   };
 
   deleteSession = (session, cb) => {
-
     const data = { target: session.id };
-    this.runSession('DELETE', data, cb);
+    this.runSession("DELETE", data, cb);
   };
 
-  signin = (user, cb) => {
-    const isCN = config.app === 'leetcode.cn';
-    const spin = isCN ? helper.spin('Signing in leetcode.cn') : helper.spin('Signing in leetcode.com');
+  signin = (user: any, cb: any) => {
     let that = this;
-    request(config.sys.urls.login, function (e, resp, _) {
-      spin.stop();
+    // eslint-disable-next-line @typescript-eslint/no-unused-vars
+    request(configUtils.sys.urls.login, function (e: any, resp: any, _) {
       e = that.checkError(e, resp, 200);
       if (e) return cb(e);
-
-      user.loginCSRF = helper.getSetCookieValue(resp, 'csrftoken');
-
+      user.loginCSRF = commUtils.getSetCookieValue(resp, "csrftoken");
       const opts = {
-        url: config.sys.urls.login,
+        url: configUtils.sys.urls.login,
         headers: {
-          Origin: config.sys.urls.base,
-          Referer: config.sys.urls.login,
-          Cookie: 'csrftoken=' + user.loginCSRF + ';'
+          Origin: configUtils.sys.urls.base,
+          Referer: configUtils.sys.urls.login,
+          Cookie: "csrftoken=" + user.loginCSRF + ";",
         },
         form: {
           csrfmiddlewaretoken: user.loginCSRF,
           login: user.login,
-          password: user.pass
-        }
+          password: user.pass,
+        },
       };
-      request.post(opts, function (e, resp, _) {
+      // eslint-disable-next-line @typescript-eslint/no-unused-vars
+      request.post(opts, function (e: any, resp: any, _) {
         if (e) return cb(e);
-        if (resp.statusCode !== 302) return cb('invalid password?');
+        if (resp.statusCode !== 302) return cb("invalid password?");
 
-        user.sessionCSRF = helper.getSetCookieValue(resp, 'csrftoken');
-        user.sessionId = helper.getSetCookieValue(resp, 'LEETCODE_SESSION');
-        session.saveUser(user);
+        user.sessionCSRF = commUtils.getSetCookieValue(resp, "csrftoken");
+        user.sessionId = commUtils.getSetCookieValue(resp, "LEETCODE_SESSION");
+        sessionUtils.saveUser(user);
         return cb(null, user);
       });
     });
@@ -517,15 +469,15 @@ class LeetCode extends MyPluginBase {
     let that = this;
     this.getFavorites(function (e, favorites) {
       if (!e) {
-        const f = favorites.favorites.private_favorites.find((f) => f.name === 'Favorite');
+        const f = favorites.favorites.private_favorites.find((f) => f.name === "Favorite");
         if (f) {
           user.hash = f.id_hash;
           user.name = favorites.user_name;
         } else {
-          log.warn('Favorite not found?');
+          reply.warn("Favorite not found?");
         }
       } else {
-        log.warn('Failed to retrieve user favorites: ' + e);
+        reply.warn("Failed to retrieve user favorites: " + e);
       }
 
       that.getUserInfo(function (e, _user) {
@@ -533,7 +485,7 @@ class LeetCode extends MyPluginBase {
           user.paid = _user.isCurrentUserPremium;
           user.name = _user.username;
         }
-        session.saveUser(user);
+        sessionUtils.saveUser(user);
         return cb(null, user);
       });
     });
@@ -553,7 +505,7 @@ class LeetCode extends MyPluginBase {
     const reCsrfResult = csrfPattern.exec(cookie);
     const reSessionResult = SessionPattern.exec(cookie);
     if (reSessionResult === null || reCsrfResult === null) {
-      return cb('invalid cookie?');
+      return cb("invalid cookie?");
     }
     return {
       sessionId: reSessionResult[1],
@@ -563,15 +515,16 @@ class LeetCode extends MyPluginBase {
 
   requestLeetcodeAndSave = (request, leetcodeUrl, user, cb) => {
     let that = this;
+    // eslint-disable-next-line @typescript-eslint/no-unused-vars
     request.get({ url: leetcodeUrl }, function (_, resp, __) {
       const redirectUri = resp.request.uri.href;
-      if (redirectUri !== config.sys.urls.leetcode_redirect) {
-        return cb('Login failed. Please make sure the credential is correct.');
+      if (redirectUri !== configUtils.sys.urls.leetcode_redirect) {
+        return cb("Login failed. Please make sure the credential is correct.");
       }
       const cookieData = that.parseCookie(resp.request.headers.cookie, cb);
       user.sessionId = cookieData.sessionId;
       user.sessionCSRF = cookieData.sessionCSRF;
-      session.saveUser(user);
+      sessionUtils.saveUser(user);
       that.getUser(user, cb);
     });
   };
@@ -580,158 +533,156 @@ class LeetCode extends MyPluginBase {
     const cookieData = this.parseCookie(user.cookie, cb);
     user.sessionId = cookieData.sessionId;
     user.sessionCSRF = cookieData.sessionCSRF;
-    session.saveUser(user);
+    sessionUtils.saveUser(user);
     this.getUser(user, cb);
   };
 
   githubLogin = (user, cb) => {
-    const urls = config.sys.urls;
+    const urls = configUtils.sys.urls;
     const leetcodeUrl = urls.github_login;
     const _request = request.defaults({ jar: true });
     let that = this;
     _request(urls.github_login_request, function (_, __, body) {
-
       const authenticityToken = body.match(/name="authenticity_token" value="(.*?)"/);
       let gaId = body.match(/name="ga_id" value="(.*?)"/);
       if (!gaId) {
-        gaId = '';
+        gaId = "";
       }
       let requiredField = body.match(/name="required_field_(.*?)"/);
       const timestamp = body.match(/name="timestamp" value="(.*?)"/);
       const timestampSecret = body.match(/name="timestamp_secret" value="(.*?)"/);
 
       if (!(authenticityToken && timestamp && timestampSecret && requiredField)) {
-        return cb('Get GitHub payload failed');
+        return cb("Get GitHub payload failed");
       }
-      requiredField = 'required_field_' + requiredField[1];
+      requiredField = "required_field_" + requiredField[1];
       const options = {
         url: urls.github_session_request,
-        method: 'POST',
+        method: "POST",
         headers: {
-          'Content-Type': 'application/x-www-form-urlencoded',
+          "Content-Type": "application/x-www-form-urlencoded",
         },
         followAllRedirects: true,
         form: {
-          'login': user.login,
-          'password': user.pass,
-          'authenticity_token': authenticityToken[1],
-          'commit': encodeURIComponent('Sign in'),
-          'ga_id': gaId,
-          'webauthn-support': 'supported',
-          'webauthn-iuvpaa-support': 'unsupported',
-          'return_to': '',
-          'requiredField': '',
-          'timestamp': timestamp[1],
-          'timestamp_secret': timestampSecret[1],
+          login: user.login,
+          password: user.pass,
+          authenticity_token: authenticityToken[1],
+          commit: encodeURIComponent("Sign in"),
+          ga_id: gaId,
+          "webauthn-support": "supported",
+          "webauthn-iuvpaa-support": "unsupported",
+          return_to: "",
+          requiredField: "",
+          timestamp: timestamp[1],
+          timestamp_secret: timestampSecret[1],
         },
       };
       _request(options, function (_, resp, body) {
-
         if (resp.statusCode !== 200) {
-          return cb('GitHub login failed');
+          return cb("GitHub login failed");
         }
         if (resp.request.uri.href !== urls.github_tf_redirect) {
           return that.requestLeetcodeAndSave(_request, leetcodeUrl, user, cb);
         }
         prompt_out.colors = false;
-        prompt_out.message = '';
+        prompt_out.message = "";
         prompt_out.start();
-        prompt_out.get([
-          {
-            name: 'twoFactorCode',
-            required: true
-          }
-        ], function (e, result) {
-          if (e) return log.info(e);
-          const authenticityTokenTwoFactor = body.match(/name="authenticity_token" value="(.*?)"/);
-          if (authenticityTokenTwoFactor === null) {
-            return cb('Get GitHub two-factor token failed');
-          }
-          const optionsTwoFactor = {
-            url: urls.github_tf_session_request,
-            method: 'POST',
-            headers: {
-              'Content-Type': 'application/x-www-form-urlencoded',
-            },
-            followAllRedirects: true,
-            form: {
-              'otp': result.twoFactorCode,
-              'authenticity_token': authenticityTokenTwoFactor[1],
-              'utf8': encodeURIComponent('✓'),
+        prompt_out.get(
+          [
+            {
+              name: "twoFactorCode",
+              required: true,
             },
-          };
-          _request(optionsTwoFactor, function (_, resp, __) {
-
-            if (resp.request.uri.href === urls.github_tf_session_request) {
-              return cb('Invalid two-factor code please check');
+          ],
+          function (e, result) {
+            if (e) return reply.info(e);
+            const authenticityTokenTwoFactor = body.match(/name="authenticity_token" value="(.*?)"/);
+            if (authenticityTokenTwoFactor === null) {
+              return cb("Get GitHub two-factor token failed");
             }
-            that.requestLeetcodeAndSave(_request, leetcodeUrl, user, cb);
-          });
-        });
+            const optionsTwoFactor = {
+              url: urls.github_tf_session_request,
+              method: "POST",
+              headers: {
+                "Content-Type": "application/x-www-form-urlencoded",
+              },
+              followAllRedirects: true,
+              form: {
+                otp: result.twoFactorCode,
+                authenticity_token: authenticityTokenTwoFactor[1],
+                utf8: encodeURIComponent("✓"),
+              },
+            };
+            // eslint-disable-next-line @typescript-eslint/no-unused-vars
+            _request(optionsTwoFactor, function (_, resp, __) {
+              if (resp.request.uri.href === urls.github_tf_session_request) {
+                return cb("Invalid two-factor code please check");
+              }
+              that.requestLeetcodeAndSave(_request, leetcodeUrl, user, cb);
+            });
+          }
+        );
       });
     });
   };
 
   linkedinLogin = (user, cb) => {
-    const urls = config.sys.urls;
+    const urls = configUtils.sys.urls;
     const leetcodeUrl = urls.linkedin_login;
     const _request = request.defaults({
       jar: true,
       headers: {
-        'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36'
-      }
+        "User-Agent":
+          "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36",
+      },
     });
     let that = this;
     _request(urls.linkedin_login_request, function (_, resp, body) {
-
       if (resp.statusCode !== 200) {
-        return cb('Get LinkedIn session failed');
+        return cb("Get LinkedIn session failed");
       }
       const csrfToken = body.match(/input type="hidden" name="csrfToken" value="(.*?)"/);
       const loginCsrfToken = body.match(/input type="hidden" name="loginCsrfParam" value="(.*?)"/);
       const sIdString = body.match(/input type="hidden" name="sIdString" value="(.*?)"/);
       const pageInstance = body.match(/input type="hidden" name="pageInstance" value="(.*?)"/);
       if (!(csrfToken && loginCsrfToken && sIdString && pageInstance)) {
-        return cb('Get LinkedIn payload failed');
+        return cb("Get LinkedIn payload failed");
       }
       const options = {
         url: urls.linkedin_session_request,
-        method: 'POST',
+        method: "POST",
         headers: {
-          'Content-Type': 'application/x-www-form-urlencoded',
+          "Content-Type": "application/x-www-form-urlencoded",
         },
         followAllRedirects: true,
         form: {
-          'csrfToken': csrfToken[1],
-          'session_key': user.login,
-          'ac': 2,
-          'sIdString': sIdString[1],
-          'parentPageKey': 'd_checkpoint_lg_consumerLogin',
-          'pageInstance': pageInstance[1],
-          'trk': 'public_profile_nav-header-signin',
-          'authUUID': '',
-          'session_redirect': 'https://www.linkedin.com/feed/',
-          'loginCsrfParam': loginCsrfToken[1],
-          'fp_data': 'default',
-          '_d': 'd',
-          'showGoogleOneTapLogin': true,
-          'controlId': 'd_checkpoint_lg_consumerLogin-login_submit_button',
-          'session_password': user.pass,
-          'loginFlow': 'REMEMBER_ME_OPTIN'
+          csrfToken: csrfToken[1],
+          session_key: user.login,
+          ac: 2,
+          sIdString: sIdString[1],
+          parentPageKey: "d_checkpoint_lg_consumerLogin",
+          pageInstance: pageInstance[1],
+          trk: "public_profile_nav-header-signin",
+          authUUID: "",
+          session_redirect: "https://www.linkedin.com/feed/",
+          loginCsrfParam: loginCsrfToken[1],
+          fp_data: "default",
+          _d: "d",
+          showGoogleOneTapLogin: true,
+          controlId: "d_checkpoint_lg_consumerLogin-login_submit_button",
+          session_password: user.pass,
+          loginFlow: "REMEMBER_ME_OPTIN",
         },
       };
+      // eslint-disable-next-line @typescript-eslint/no-unused-vars
       _request(options, function (_, resp, __) {
-
         if (resp.statusCode !== 200) {
-          return cb('LinkedIn login failed');
+          return cb("LinkedIn login failed");
         }
         that.requestLeetcodeAndSave(_request, leetcodeUrl, user, cb);
       });
     });
   };
-
 }
 
-
-
 export const pluginObj: LeetCode = new LeetCode();
diff --git a/src/childProcessCall/plugins/retry.ts b/src/rpc/actionChain/chainNode/retry.ts
similarity index 62%
rename from src/childProcessCall/plugins/retry.ts
rename to src/rpc/actionChain/chainNode/retry.ts
index 8ca06fa..26ae28c 100644
--- a/src/childProcessCall/plugins/retry.ts
+++ b/src/rpc/actionChain/chainNode/retry.ts
@@ -1,44 +1,43 @@
 /*
- * Filename: https://github.com/ccagml/vscode-leetcode-problem-rating/src/childProcessCall/plugins/retry.ts
- * Path: https://github.com/ccagml/vscode-leetcode-problem-rating
- * Created Date: Thursday, October 27th 2022, 7:43:29 pm
+ * Filename: /home/cc/vscode-leetcode-problem-rating/src/rpc/actionChain/retry.ts
+ * Path: /home/cc/vscode-leetcode-problem-rating
+ * Created Date: Monday, November 14th 2022, 4:04:31 pm
  * Author: ccagml
  *
  * Copyright (c) 2022 ccagml . All rights reserved.
  */
 
+import { ChainNodeBase } from "../chainNodeBase";
+import { configUtils } from "../../utils/configUtils";
+import { sessionUtils } from "../../utils/sessionUtils";
 
-
-import { MyPluginBase } from "../my_plugin_base";
-import { config } from "../config";
-import { session } from "../session";
-
-
-class RetryPlugin extends MyPluginBase {
+class RetryPlugin extends ChainNodeBase {
   id = 30;
-  name = 'retry';
+  name = "retry";
   builtin = true;
   count = {};
 
   canRetry = (e, name) => {
-    return config.autologin.enable &&
-      (e === session.errors.EXPIRED) &&
-      (this.count[name] || 0) < config.autologin.retry;
+    return (
+      configUtils.autologin.enable &&
+      e === sessionUtils.errors.EXPIRED &&
+      (this.count[name] || 0) < configUtils.autologin.retry
+    );
   };
   init = () => {
     const names = [
-      'activateSession',
-      'createSession',
-      'deleteSession',
-      'getProblems',
-      'getProblem',
-      'getSessions',
-      'getSubmissions',
-      'getSubmission',
-      'getFavorites',
-      'testProblem',
-      'submitProblem',
-      'starProblem'
+      "activateSession",
+      "createSession",
+      "deleteSession",
+      "getProblems",
+      "getProblem",
+      "getSessions",
+      "getSubmissions",
+      "getSubmission",
+      "getFavorites",
+      "testProblem",
+      "submitProblem",
+      "starProblem",
     ];
     let that = this;
     for (let name of names) {
@@ -73,10 +72,8 @@ class RetryPlugin extends MyPluginBase {
   // expired immediately. In that case we will try to re-login in
   // the backend to give a seamless user experience.
   relogin = (cb) => {
-
-    const user = session.getUser();
+    const user = sessionUtils.getUser();
     if (!user) {
-
       return cb();
     }
 
@@ -89,8 +86,6 @@ class RetryPlugin extends MyPluginBase {
       return cb();
     });
   };
-
 }
 
-
 export const pluginObj: RetryPlugin = new RetryPlugin();
diff --git a/src/rpc/actionChain/chainNode/solution.discuss.ts b/src/rpc/actionChain/chainNode/solution.discuss.ts
new file mode 100644
index 0000000..35afd37
--- /dev/null
+++ b/src/rpc/actionChain/chainNode/solution.discuss.ts
@@ -0,0 +1,110 @@
+/*
+ * Filename: /home/cc/vscode-leetcode-problem-rating/src/rpc/actionChain/solution.discuss.ts
+ * Path: /home/cc/vscode-leetcode-problem-rating
+ * Created Date: Monday, November 14th 2022, 4:04:31 pm
+ * Author: ccagml
+ *
+ * Copyright (c) 2022 ccagml . All rights reserved.
+ */
+
+let request = require("request");
+
+import { reply } from "../../utils/ReplyUtils";
+import { sessionUtils } from "../../utils/sessionUtils";
+import { ChainNodeBase } from "../chainNodeBase";
+
+class SolutionDiscuss extends ChainNodeBase {
+  id = 200;
+  name = "solution.discuss";
+  builtin = true;
+  constructor() {
+    super();
+  }
+
+  getProblem = (problem, needTranslation, cb) => {
+    this.next.getProblem(problem, needTranslation, function (e, problem) {
+      if (e || !sessionUtils.argv.solution) return cb(e, problem);
+
+      let lang = sessionUtils.argv.lang;
+      getSolution(problem, lang, function (e, solution) {
+        if (e) return cb(e);
+        if (!solution) return reply.error("Solution not found for " + lang);
+
+        let link = URL_DISCUSS.replace("$slug", problem.slug).replace("$id", solution.id);
+        let content = solution.post.content.replace(/\\n/g, "\n").replace(/\\t/g, "\t");
+
+        reply.info();
+        reply.info(problem.name);
+        reply.info();
+        reply.info(solution.title);
+        reply.info();
+        reply.info(link);
+        reply.info();
+        reply.info("* Lang:    " + lang);
+        reply.info("* Author:  " + solution.post.author.username);
+        reply.info("* Votes:   " + solution.post.voteCount);
+        reply.info();
+        reply.info(content);
+      });
+    });
+  };
+}
+
+let URL_DISCUSSES = "https://leetcode.com/graphql";
+let URL_DISCUSS = "https://leetcode.com/problems/$slug/discuss/$id";
+
+function getSolution(problem, lang, cb) {
+  if (!problem) return cb();
+
+  if (lang === "python3") lang = "python";
+
+  let opts = {
+    url: URL_DISCUSSES,
+    json: true,
+    body: {
+      query: [
+        "query questionTopicsList($questionId: String!, $orderBy: TopicSortingOption, $skip: Int, $query: String, $first: Int!, $tags: [String!]) {",
+        "  questionTopicsList(questionId: $questionId, orderBy: $orderBy, skip: $skip, query: $query, first: $first, tags: $tags) {",
+        "    ...TopicsList",
+        "  }",
+        "}",
+        "fragment TopicsList on TopicConnection {",
+        "  totalNum",
+        "  edges {",
+        "    node {",
+        "      id",
+        "      title",
+        "      post {",
+        "        content",
+        "        voteCount",
+        "        author {",
+        "          username",
+        "        }",
+        "      }",
+        "    }",
+        "  }",
+        "}",
+      ].join("\n"),
+
+      operationName: "questionTopicsList",
+      variables: JSON.stringify({
+        query: "",
+        first: 1,
+        skip: 0,
+        orderBy: "most_votes",
+        questionId: "" + problem.id,
+        tags: [lang],
+      }),
+    },
+  };
+  request(opts, function (e, resp, body) {
+    if (e) return cb(e);
+    if (resp.statusCode !== 200) return cb({ msg: "http error", statusCode: resp.statusCode });
+
+    const solutions = body.data.questionTopicsList.edges;
+    const solution = solutions.length > 0 ? solutions[0].node : null;
+    return cb(null, solution);
+  });
+}
+
+export const pluginObj: SolutionDiscuss = new SolutionDiscuss();
diff --git a/src/rpc/actionChain/chainNodeBase.ts b/src/rpc/actionChain/chainNodeBase.ts
new file mode 100644
index 0000000..3147fdb
--- /dev/null
+++ b/src/rpc/actionChain/chainNodeBase.ts
@@ -0,0 +1,117 @@
+import { commUtils } from "../utils/commUtils";
+import { storageUtils } from "../utils/storageUtils";
+
+export class ChainNodeBase {
+  next: ChainNodeBase; // 下一个点
+  enabled: boolean;
+  builtin: boolean = true;
+  name: string; // 点的名称
+  deleted: boolean;
+
+  public init() {}
+
+  public save(): void {
+    const stats = storageUtils.getCache(commUtils.KEYS.plugins) || {};
+
+    if (this.deleted) delete stats[this.name];
+    else stats[this.name] = this.enabled;
+
+    storageUtils.setCache(commUtils.KEYS.plugins, stats);
+  }
+
+  public setNext(next: ChainNodeBase): void {
+    Object.setPrototypeOf(this, next);
+    this.next = next;
+  }
+  public getProblems(Translate: boolean, cb: Function): void {
+    this.next.getProblems(Translate, cb);
+  }
+  public getQuestionOfToday(cb: Function): void {
+    this.next.getQuestionOfToday(cb);
+  }
+
+  public getRatingOnline(cb: Function): void {
+    this.next.getRatingOnline(cb);
+  }
+
+  public getTestApi(username, cb: Function): void {
+    this.next.getTestApi(username, cb);
+  }
+  public getUserContestP(username, cb: Function): void {
+    this.next.getUserContestP(username, cb);
+  }
+  public getProblemsTitle(cb: Function): void {
+    this.next.getProblemsTitle(cb);
+  }
+  public createSession(a, cb: Function): void {
+    this.next.createSession(a, cb);
+  }
+  public getSessions(cb: Function): void {
+    this.next.getSessions(cb);
+  }
+  public activateSession(s, cb: Function): void {
+    this.next.activateSession(s, cb);
+  }
+  public deleteSession(s, cb: Function): void {
+    this.next.deleteSession(s, cb);
+  }
+  public updateProblem(a, b): void {
+    this.next.updateProblem(a, b);
+  }
+  public getSubmissions(s, cb: Function): void {
+    this.next.getSubmissions(s, cb);
+  }
+  public getSubmission(s, cb: Function): void {
+    this.next.getSubmission(s, cb);
+  }
+  public submitProblem(s, cb: Function): void {
+    this.next.submitProblem(s, cb);
+  }
+  public testProblem(s, cb: Function): void {
+    this.next.testProblem(s, cb);
+  }
+  public login(user, cb: Function): void {
+    this.next.login(user, cb);
+  }
+  public logout(user, cb): void {
+    this.next.logout(user, cb);
+  }
+  public githubLogin(user, cb: Function): void {
+    this.next.githubLogin(user, cb);
+  }
+  public linkedinLogin(user, cb: Function): void {
+    this.next.linkedinLogin(user, cb);
+  }
+  public cookieLogin(user, cb: Function): void {
+    this.next.cookieLogin(user, cb);
+  }
+  public filterProblems(opts, cb: Function): void {
+    this.next.filterProblems(opts, cb);
+  }
+
+  public getProblem(keyword, needTranslation, cb: Function): void {
+    this.next.getProblem(keyword, needTranslation, cb);
+  }
+
+  public starProblem(problem, starred, cb: Function): void {
+    this.next.starProblem(problem, starred, cb);
+  }
+  public exportProblem(problem, opts): void {
+    this.next.exportProblem(problem, opts);
+  }
+
+  public getTodayQuestion(cb: Function): void {
+    this.next.getTodayQuestion(cb);
+  }
+
+  public getQueryZ(username, cb: Function): void {
+    this.next.getQueryZ(username, cb);
+  }
+
+  public getUserContest(username, cb: Function): void {
+    this.next.getUserContest(username, cb);
+  }
+  public getRating(cb: Function): void {
+    this.next.getRating(cb);
+  }
+}
diff --git a/src/rpc/childMain.ts b/src/rpc/childMain.ts
new file mode 100644
index 0000000..f7e2fb9
--- /dev/null
+++ b/src/rpc/childMain.ts
@@ -0,0 +1,37 @@
+/*
+ * Filename: https://github.com/ccagml/vscode-leetcode-problem-rating/src/rpc/cli.ts
+ * Path: https://github.com/ccagml/vscode-leetcode-problem-rating
+ * Created Date: Thursday, October 27th 2022, 7:43:29 pm
+ * Author: ccagml
+ *
+ * Copyright (c) 2022 ccagml . All rights reserved.
+ */
+
+import { chainMgr } from "./actionChain/chainManager";
+import { corePlugin } from "./actionChain/chainNode/core";
+import { configUtils } from "./utils/configUtils";
+import { reply } from "./utils/ReplyUtils";
+import { storageUtils } from "./utils/storageUtils";
+import { apiFactory } from "./factory/apiFactory";
+import { IApi } from "./factory/apiBase";
+
+class Main {
+  constructor() {
+    this.exec();
+  }
+  public exec() {
+    process.stdout.on("error", function (e) {
+      if (e.code === "EPIPE") process.exit();
+    });
+    configUtils.init(JSON.parse(process.env.ccagml || "{}"));
+    reply.init();
+    storageUtils.init();
+    chainMgr.init(corePlugin);
+
+    let com_str: string = process.argv[2];
+    let curApi: IApi | undefined = apiFactory.getApi(com_str);
+    curApi?.call(curApi?.callArg(process.argv));
+  }
+}
+
+export const main: Main = new Main();
diff --git a/src/rpc/factory/api/cacheApi.ts b/src/rpc/factory/api/cacheApi.ts
new file mode 100644
index 0000000..e164128
--- /dev/null
+++ b/src/rpc/factory/api/cacheApi.ts
@@ -0,0 +1,49 @@
+/*
+ * Filename: /home/cc/vscode-leetcode-problem-rating/src/rpc/factory/api/cacheApi.ts
+ * Path: /home/cc/vscode-leetcode-problem-rating
+ * Created Date: Thursday, November 17th 2022, 11:44:14 am
+ * Author: ccagml
+ *
+ * Copyright (c) 2022 ccagml . All rights reserved.
+ */
+
+import { storageUtils } from "../../utils/storageUtils";
+import { sessionUtils } from "../../utils/sessionUtils";
+import { ApiBase } from "../apiBase";
+
+class CacheApi extends ApiBase {
+  constructor() {
+    super();
+  }
+
+  callArg(argv) {
+    let argv_config = this.api_argv().option("d", {
+      alias: "delete",
+      type: "boolean",
+      describe: "Delete cache by keyword",
+      default: false,
+    });
+    argv_config.parseArgFromCmd(argv);
+
+    return argv_config.get_result();
+  }
+
+  call(argv) {
+    sessionUtils.argv = argv;
+
+    const name = argv.keyword || "";
+    const isInteger = Number.isInteger(Number(name));
+
+    const all_data_file = storageUtils.listCache().filter(function (f) {
+      return name.length === 0 || (isInteger ? f.name.startsWith(name + ".") : f.name === name);
+    });
+
+    if (argv.delete) {
+      for (let f of all_data_file) {
+        storageUtils.delCache(f.name);
+      }
+    }
+  }
+}
+
+export const cacheApi: CacheApi = new CacheApi();
diff --git a/src/rpc/factory/api/listApi.ts b/src/rpc/factory/api/listApi.ts
new file mode 100644
index 0000000..5c5e6cb
--- /dev/null
+++ b/src/rpc/factory/api/listApi.ts
@@ -0,0 +1,91 @@
+/*
+ * Filename: /home/cc/vscode-leetcode-problem-rating/src/rpc/factory/api/listApi.ts
+ * Path: /home/cc/vscode-leetcode-problem-rating
+ * Created Date: Thursday, November 17th 2022, 11:44:14 am
+ * Author: ccagml
+ *
+ * Copyright (c) 2022 ccagml . All rights reserved.
+ */
+
+import { reply } from "../../utils/ReplyUtils";
+import { sessionUtils } from "../../utils/sessionUtils";
+import { ApiBase } from "../apiBase";
+import { chainMgr } from "../../actionChain/chainManager";
+
+class ListApi extends ApiBase {
+  constructor() {
+    super();
+  }
+
+  callArg(argv) {
+    let argv_config = this.api_argv()
+      .option("q", {
+        alias: "query",
+        type: "string",
+        default: "",
+        describe: [
+          "Filter questions by condition:",
+          "Uppercase means negative",
+          "e = easy     E = m+h",
+          "m = medium   M = e+h",
+          "h = hard     H = e+m",
+          "d = done     D = not done",
+          "l = locked   L = non locked",
+          "s = starred  S = not starred",
+        ].join("\n"),
+      })
+      .option("s", {
+        alias: "stat",
+        type: "boolean",
+        default: false,
+        describe: "Show statistics of listed questions",
+      })
+      .option("t", {
+        alias: "tag",
+        type: "array",
+        default: [],
+        describe: "Filter questions by tag",
+      })
+      .option("x", {
+        alias: "extra",
+        type: "boolean",
+        default: false,
+        describe: "Show extra details: category, companies, tags.",
+      })
+      .option("T", {
+        alias: "dontTranslate",
+        type: "boolean",
+        default: false,
+        describe: "Set to true to disable endpoint's translation",
+      })
+      .positional("keyword", {
+        type: "string",
+        default: "",
+        describe: "Filter questions by keyword",
+      });
+
+    argv_config.parseArgFromCmd(argv);
+
+    return argv_config.get_result();
+  }
+
+  call(argv) {
+    sessionUtils.argv = argv;
+    chainMgr.getChainHead().filterProblems(argv, function (e, problems) {
+      if (e) return reply.info(e);
+      let new_objcet: Array = [];
+      problems.forEach((element) => {
+        let temp_ele: any = {};
+        for (const key in element) {
+          if (key != "link") {
+            temp_ele[key] = element[key];
+          }
+        }
+        new_objcet.push(temp_ele);
+      });
+      reply.info(JSON.stringify(new_objcet));
+    });
+  }
+}
+
+export const listApi: ListApi = new ListApi();
diff --git a/src/rpc/factory/api/pluginApi.ts b/src/rpc/factory/api/pluginApi.ts
new file mode 100644
index 0000000..7712132
--- /dev/null
+++ b/src/rpc/factory/api/pluginApi.ts
@@ -0,0 +1,82 @@
+/*
+ * Filename: /home/cc/vscode-leetcode-problem-rating/src/rpc/factory/api/pluginApi.ts
+ * Path: /home/cc/vscode-leetcode-problem-rating
+ * Created Date: Thursday, November 17th 2022, 11:44:14 am
+ * Author: ccagml
+ *
+ * Copyright (c) 2022 ccagml . All rights reserved.
+ */
+
+import { configUtils } from "../../utils/configUtils";
+import { reply } from "../../utils/ReplyUtils";
+import { chainMgr } from "../../actionChain/chainManager";
+import { sessionUtils } from "../../utils/sessionUtils";
+import { ApiBase } from "../apiBase";
+
+class PluginApi extends ApiBase {
+  constructor() {
+    super();
+  }
+
+  callArg(argv) {
+    let argv_config = this.api_argv()
+      .option("d", {
+        alias: "disable",
+        type: "boolean",
+        describe: "Disable plugin",
+        default: false,
+      })
+      .option("e", {
+        alias: "enable",
+        type: "boolean",
+        describe: "Enable plugin",
+        default: false,
+      })
+      .option("i", {
+        alias: "install",
+        type: "boolean",
+        describe: "Install plugin",
+        default: false,
+      })
+      .positional("name", {
+        type: "string",
+        describe: "Filter plugin by name",
+        default: "",
+      });
+
+    argv_config.parseArgFromCmd(argv);
+
+    return argv_config.get_result();
+  }
+
+  call(argv) {
+    sessionUtils.argv = argv;
+
+    let all_plugin = chainMgr.installed;
+    const name = argv.name;
+
+    if (name) {
+      all_plugin = all_plugin.filter((x) => x.name === name);
+    }
+    if (all_plugin.length === 0) {
+      return reply.fatal("Plugin not found!");
+    }
+
+    const p = all_plugin[0];
+    if (argv.enable) {
+      p.enabled = true;
+      p.save();
+    } else if (argv.disable) {
+      p.enabled = false;
+      p.save();
+    } else if (argv.delete) {
+      // p.delete();
+      p.save();
+      chainMgr.init(undefined);
+    } else if (argv.config) {
+      reply.info(JSON.stringify(configUtils.plugins[name] || {}, null, 2));
+    }
+  }
+}
+
+export const pluginApi: PluginApi = new PluginApi();
diff --git a/src/rpc/factory/api/queryApi.ts b/src/rpc/factory/api/queryApi.ts
new file mode 100644
index 0000000..a568079
--- /dev/null
+++ b/src/rpc/factory/api/queryApi.ts
@@ -0,0 +1,93 @@
+/*
+ * Filename: /home/cc/vscode-leetcode-problem-rating/src/rpc/factory/api/queryApi.ts
+ * Path: /home/cc/vscode-leetcode-problem-rating
+ * Created Date: Thursday, November 17th 2022, 11:44:14 am
+ * Author: ccagml
+ *
+ * Copyright (c) 2022 ccagml . All rights reserved.
+ */
+
+import { reply } from "../../utils/ReplyUtils";
+import { sessionUtils } from "../../utils/sessionUtils";
+import { ApiBase } from "../apiBase";
+
+import { chainMgr } from "../../actionChain/chainManager";
+
+class QueryApi extends ApiBase {
+  constructor() {
+    super();
+  }
+  callArg(argv) {
+    let argv_config = this.api_argv()
+      .option("T", {
+        alias: "dontTranslate",
+        type: "boolean",
+        default: false,
+        describe: "Set to true to disable endpoint's translation",
+      })
+      .option("a", {
+        alias: "getTodayQuestion",
+        type: "boolean",
+        default: false,
+        describe: "getTodayQuestion",
+      })
+      .option("b", {
+        alias: "username",
+        type: "string",
+        default: "",
+        describe: "user name",
+      })
+      .option("c", {
+        alias: "getRating",
+        type: "boolean",
+        default: false,
+        describe: "ranking",
+      })
+      .option("z", {
+        alias: "test",
+        type: "string",
+        default: "",
+        describe: "test",
+      });
+    argv_config.parseArgFromCmd(argv);
+    return argv_config.get_result();
+  }
+
+  call(argv) {
+    sessionUtils.argv = argv;
+    if (argv.a) {
+      chainMgr.getChainHead().getTodayQuestion(function (e, result) {
+        if (e) return;
+        reply.info(JSON.stringify(result));
+      });
+    } else if (argv.b) {
+      chainMgr.getChainHead().getUserContest(argv.b, function (e, result) {
+        if (e) return;
+        reply.info(JSON.stringify(result));
+      });
+    } else if (argv.c) {
+      chainMgr.getChainHead().getRating(function (e, result) {
+        if (e) {
+          let log_data = {
+            code: 101,
+            data: {},
+          };
+          reply.info(JSON.stringify(log_data));
+          return;
+        }
+        let log_data = {
+          code: 100,
+          data: result,
+        };
+        reply.info(JSON.stringify(log_data));
+      });
+    } else if (argv.z) {
+      chainMgr.getChainHead().getQueryZ(argv.z, function (e, result) {
+        if (e) return;
+        reply.info(JSON.stringify(result));
+      });
+    }
+  }
+}
+
+export const queryApi: QueryApi = new QueryApi();
diff --git a/src/rpc/factory/api/showApi.ts b/src/rpc/factory/api/showApi.ts
new file mode 100644
index 0000000..3ef7823
--- /dev/null
+++ b/src/rpc/factory/api/showApi.ts
@@ -0,0 +1,204 @@
+/*
+ * Filename: /home/cc/vscode-leetcode-problem-rating/src/rpc/factory/api/showApi.ts
+ * Path: /home/cc/vscode-leetcode-problem-rating
+ * Created Date: Thursday, November 17th 2022, 11:44:14 am
+ * Author: ccagml
+ *
+ * Copyright (c) 2022 ccagml . All rights reserved.
+ */
+
+let util = require("util");
+let childProcess = require("child_process");
+
+import { storageUtils } from "../../utils/storageUtils";
+
+import { reply } from "../../utils/ReplyUtils";
+import { configUtils } from "../../utils/configUtils";
+
+import { sessionUtils } from "../../utils/sessionUtils";
+import { ApiBase } from "../apiBase";
+import { chainMgr } from "../../actionChain/chainManager";
+
+class ShowApi extends ApiBase {
+  constructor() {
+    super();
+  }
+
+  callArg(argv) {
+    let argv_config = this.api_argv()
+      .option("c", {
+        alias: "codeonly",
+        type: "boolean",
+        default: false,
+        describe: "Only show code template",
+      })
+      .option("e", {
+        alias: "editor",
+        type: "string",
+        describe: "Open source code in editor",
+      })
+      .option("g", {
+        alias: "gen",
+        type: "boolean",
+        default: false,
+        describe: "Generate source code",
+      })
+      .option("l", {
+        alias: "lang",
+        type: "string",
+        default: configUtils.code.lang,
+        describe: "Programming language of the source code",
+        choices: configUtils.sys.langs,
+      })
+      .option("o", {
+        alias: "outdir",
+        type: "string",
+        describe: "Where to save source code",
+        default: ".",
+      })
+      .option("q", {
+        alias: "query",
+        type: "string",
+        default: "",
+        describe: [
+          "Filter questions by condition:",
+          "Uppercase means negative",
+          "e = easy     E = m+h",
+          "m = medium   M = e+h",
+          "h = hard     H = e+m",
+          "d = done     D = not done",
+          "l = locked   L = non locked",
+          "s = starred  S = not starred",
+        ].join("\n"),
+      })
+      .option("t", {
+        alias: "tag",
+        type: "array",
+        default: [],
+        describe: "Filter questions by tag",
+      })
+      .option("x", {
+        alias: "extra",
+        type: "boolean",
+        default: false,
+        describe: "Show extra question details in source code",
+      })
+      .option("T", {
+        alias: "dontTranslate",
+        type: "boolean",
+        default: false,
+        describe: "Set to true to disable endpoint's translation",
+      })
+      .positional("keyword", {
+        type: "string",
+        default: "",
+        describe: "Show question by name or id",
+      });
+    argv_config.parseArgFromCmd(argv);
+    return argv_config.get_result();
+  }
+  genFileName(problem, opts) {
+    const path = require("path");
+    const params = [storageUtils.fmt(configUtils.file.show, problem), "", storageUtils.getFileExtByLanguage(opts.lang)];
+
+    // try new name to avoid overwrite by mistake
+    for (let i = 0; ; ++i) {
+      const name = path.join(opts.outdir, params.join(".").replace(/\.+/g, "."));
+      if (!storageUtils.exist(name)) return name;
+      params[1] = i;
+    }
+  }
+
+  showProblem(problem, argv) {
+    const taglist = [problem.category]
+      .concat(problem.companies || [])
+      .concat(problem.tags || [])
+      .map((x) => " " + x + " ")
+      .join(" ");
+    const langlist = problem.templates
+      .map((x) => " " + x.value + " ")
+      .sort()
+      .join(" ");
+
+    let code;
+    const needcode = argv.gen || argv.codeonly;
+    if (needcode) {
+      const template = problem.templates.find((x) => x.value === argv.lang);
+      if (!template) {
+        reply.info('Not supported language "' + argv.lang + '"');
+        reply.warn("Supported languages: " + langlist);
+        return;
+      }
+
+      const opts = {
+        lang: argv.lang,
+        code: template.defaultCode,
+        tpl: argv.extra ? "detailed" : "codeonly",
+      };
+      code = chainMgr.getChainHead().exportProblem(problem, opts);
+    }
+
+    let filename;
+    if (argv.gen) {
+      storageUtils.mkdir(argv.outdir);
+      filename = this.genFileName(problem, argv);
+      storageUtils.write(filename, code);
+
+      if (argv.editor !== undefined) {
+        childProcess.spawn(argv.editor || configUtils.code.editor, [filename], {
+          // in case your editor of choice is vim or emacs
+          stdio: "inherit",
+        });
+      }
+    } else {
+      if (argv.codeonly) {
+        reply.info(code);
+        return;
+      }
+    }
+
+    reply.info(`[${problem.fid}] ${problem.name}`);
+    reply.info();
+    reply.info(problem.link);
+    if (argv.extra) {
+      reply.info();
+      reply.info("Tags:  " + taglist);
+      reply.info();
+      reply.info("Langs: " + langlist);
+    }
+
+    reply.info();
+    reply.info(`* ${problem.category}`);
+    reply.info(`* ${problem.level} (${problem.percent.toFixed(2)}%)`);
+
+    if (problem.likes) reply.info(`* Likes:    ${problem.likes}`);
+    if (problem.dislikes) reply.info(`* Dislikes: ${problem.dislikes}`);
+    else reply.info(`* Dislikes: -`);
+    if (problem.totalAC) reply.info(`* Total Accepted:    ${problem.totalAC}`);
+    if (problem.totalSubmit) reply.info(`* Total Submissions: ${problem.totalSubmit}`);
+    if (problem.testable && problem.testcase) {
+      let testcase_value = util.inspect(problem.testcase);
+      reply.info(`* Testcase Example:  ${testcase_value}`);
+    }
+    if (filename) reply.info(`* Source Code:       ${filename}`);
+
+    reply.info();
+    reply.info(problem.desc);
+  }
+
+  call(argv) {
+    let that = this;
+    sessionUtils.argv = argv;
+    if (argv.keyword.length > 0) {
+      // show specific one
+      chainMgr.getChainHead().getProblem(argv.keyword, !argv.dontTranslate, function (e, problem) {
+        if (e) return reply.info(e);
+        that.showProblem(problem, argv);
+      });
+    } else {
+      //
+    }
+  }
+}
+
+export const showApi: ShowApi = new ShowApi();
diff --git a/src/rpc/factory/api/starApi.ts b/src/rpc/factory/api/starApi.ts
new file mode 100644
index 0000000..69bdc7c
--- /dev/null
+++ b/src/rpc/factory/api/starApi.ts
@@ -0,0 +1,55 @@
+/*
+ * Filename: /home/cc/vscode-leetcode-problem-rating/src/rpc/factory/api/starApi.ts
+ * Path: /home/cc/vscode-leetcode-problem-rating
+ * Created Date: Thursday, November 17th 2022, 11:44:14 am
+ * Author: ccagml
+ *
+ * Copyright (c) 2022 ccagml . All rights reserved.
+ */
+
+import { reply } from "../../utils/ReplyUtils";
+
+import { sessionUtils } from "../../utils/sessionUtils";
+import { ApiBase } from "../apiBase";
+import { chainMgr } from "../../actionChain/chainManager";
+
+class StarApi extends ApiBase {
+  constructor() {
+    super();
+  }
+
+  callArg(argv) {
+    let argv_config = this.api_argv()
+      .option("d", {
+        alias: "delete",
+        type: "boolean",
+        describe: "Unstar question",
+        default: false,
+      })
+      .positional("keyword", {
+        type: "string",
+        describe: "Question name or id",
+        default: "",
+      });
+
+    argv_config.parseArgFromCmd(argv);
+
+    return argv_config.get_result();
+  }
+
+  call(argv) {
+    sessionUtils.argv = argv;
+    // translation doesn't affect question lookup
+    chainMgr.getChainHead().getProblem(argv.keyword, true, function (e, problem) {
+      if (e) return reply.info(e);
+
+      chainMgr.getChainHead().starProblem(problem, !argv.delete, function (e, starred) {
+        if (e) return reply.info(e);
+        reply.info(`[${problem.fid}] ${problem.name} ${starred ? "icon.like" : "icon.unlike"}`);
+        chainMgr.getChainHead().updateProblem(problem, { starred: starred });
+      });
+    });
+  }
+}
+
+export const starApi: StarApi = new StarApi();
diff --git a/src/childProcessCall/commands/submission.ts b/src/rpc/factory/api/submissionApi.ts
similarity index 88%
rename from src/childProcessCall/commands/submission.ts
rename to src/rpc/factory/api/submissionApi.ts
index f0ff5ef..98b2684 100644
--- a/src/childProcessCall/commands/submission.ts
+++ b/src/rpc/factory/api/submissionApi.ts
@@ -1,36 +1,29 @@
 /*
- * Filename: https://github.com/ccagml/vscode-leetcode-problem-rating/src/childProcessCall/commands/submission.ts
- * Path: https://github.com/ccagml/vscode-leetcode-problem-rating
- * Created Date: Thursday, October 27th 2022, 7:43:29 pm
+ * Filename: /home/cc/vscode-leetcode-problem-rating/src/rpc/factory/api/submission.ts
+ * Path: /home/cc/vscode-leetcode-problem-rating
+ * Created Date: Monday, November 14th 2022, 4:04:31 pm
  * Author: ccagml
  *
  * Copyright (c) 2022 ccagml . All rights reserved.
  */
 
-
-
 // let path = require('path');
 
 // let _ = require('underscore');
 
-
-
-// import { helper } from "../helper";
+// import { commUtils } from "../commUtils";
 // import { file } from "../file";
 // import { config } from "../config";
 // import { log } from "../log";
 // import { Queue } from "../queue";
 // import { corePlugin } from "../core";
-// import { session } from "../session";
-
+// import { sessionUtils } from "../session";
 
 class SubMission {
-  constructor() {
+  constructor() {}
 
-  }
-
-  // process_argv = function (argv) {
-  //   let argv_config = helper.base_argv().option('a', {
+  // callArg = function (argv) {
+  //   let argv_config = this.api_argv().option('a', {
   //     alias: 'all',
   //     type: 'boolean',
   //     default: false,
@@ -65,12 +58,11 @@ class SubMission {
   //       default: '',
   //       describe: 'Download specific question by id'
   //     });
-  //   argv_config.process_argv(argv);
+  //   argv_config.parseArgFromCmd(argv);
 
   //   return argv_config.get_result();
   // };
 
-
   // doTask(problem, queue, cb) {
   //   let that = this;
   //   const argv = queue.ctx.argv;
@@ -116,7 +108,7 @@ class SubMission {
   //     data.sid = submission.id;
   //     data.ac = submission.ac ? 'ac' : 'notac';
   //     const basename = storageUtils.fmt(config.storageUtils.submission, data);
-  //     const f = path.join(argv.outdir, basename + helper.langToExt(submission.lang));
+  //     const f = path.join(argv.outdir, basename + storageUtils.getFileExtByLanguage(submission.lang));
 
   //     storageUtils.mkdir(argv.outdir);
   //     // skip the existing cached submissions
@@ -161,6 +153,4 @@ class SubMission {
   // };
 }
 
-
-
 export const subMissionCommand: SubMission = new SubMission();
diff --git a/src/rpc/factory/api/submitApi.ts b/src/rpc/factory/api/submitApi.ts
new file mode 100644
index 0000000..2d796f8
--- /dev/null
+++ b/src/rpc/factory/api/submitApi.ts
@@ -0,0 +1,133 @@
+/*
+ * Filename: /home/cc/vscode-leetcode-problem-rating/src/rpc/factory/api/submitApi.ts
+ * Path: /home/cc/vscode-leetcode-problem-rating
+ * Created Date: Thursday, November 17th 2022, 11:44:14 am
+ * Author: ccagml
+ *
+ * Copyright (c) 2022 ccagml . All rights reserved.
+ */
+
+let util = require("util");
+let lodash = require("lodash");
+
+import { storageUtils } from "../../utils/storageUtils";
+import { reply } from "../../utils/ReplyUtils";
+
+import { sessionUtils } from "../../utils/sessionUtils";
+import { ApiBase } from "../apiBase";
+import { chainMgr } from "../../actionChain/chainManager";
+
+class SubmitApi extends ApiBase {
+  constructor() {
+    super();
+  }
+
+  callArg(argv) {
+    let argv_config = this.api_argv().positional("filename", {
+      type: "string",
+      describe: "Code file to submit",
+      default: "",
+    });
+    argv_config.parseArgFromCmd(argv);
+
+    return argv_config.get_result();
+  }
+
+  printResult(actual, k, log_obj) {
+    if (!actual.hasOwnProperty(k)) return;
+
+    const v = actual[k] || "";
+    const lines = Array.isArray(v) ? v : [v];
+    for (let line of lines) {
+      if (k !== "state") {
+        if (!log_obj.hasOwnProperty(lodash.startCase(k))) {
+          log_obj[lodash.startCase(k)] = [line];
+        } else {
+          log_obj[lodash.startCase(k)].push(line);
+        }
+      } else {
+        log_obj.messages.push(line);
+      }
+    }
+  }
+
+  printLine(log_obj, ...ret: any[]) {
+    const args = ret.slice(1);
+    const line = util.format.apply(util, args);
+    log_obj.messages.push(line);
+  }
+
+  call(argv) {
+    sessionUtils.argv = argv;
+    if (!storageUtils.exist(argv.filename)) return reply.fatal("File " + argv.filename + " not exist!");
+
+    const meta = storageUtils.meta(argv.filename);
+    let that = this;
+    // translation doesn't affect problem lookup
+    chainMgr.getChainHead().getProblem(meta, true, function (e, problem) {
+      if (e) return reply.info(e);
+
+      problem.file = argv.filename;
+      problem.lang = meta.lang;
+
+      chainMgr.getChainHead().submitProblem(problem, function (e, results) {
+        if (e) return reply.info(e);
+
+        const result = results[0];
+
+        let log_obj: any = {};
+        log_obj.messages = [];
+        log_obj.system_message = {};
+        log_obj.system_message.fid = problem.fid;
+        log_obj.system_message.id = problem.id;
+        log_obj.system_message.qid = problem.id;
+        log_obj.system_message.sub_type = "submit";
+        log_obj.system_message.accepted = false;
+
+        that.printResult(result, "state", log_obj);
+        that.printLine(log_obj, result, "%d/%d cases passed (%s)", result.passed, result.total, result.runtime);
+
+        if (result.ok) {
+          sessionUtils.updateStat("ac", 1);
+          sessionUtils.updateStat("ac.set", problem.fid);
+          log_obj.system_message.accepted = true;
+
+          (function () {
+            if (result.runtime_percentile)
+              that.printLine(
+                log_obj,
+                result,
+                "Your runtime beats %d %% of %s submissions",
+                result.runtime_percentile.toFixed(2),
+                result.lang
+              );
+            else return reply.warn("Failed to get runtime percentile.");
+            if (result.memory && result.memory_percentile)
+              that.printLine(
+                log_obj,
+                result,
+                "Your memory usage beats %d %% of %s submissions (%s)",
+                result.memory_percentile.toFixed(2),
+                result.lang,
+                result.memory
+              );
+            else return reply.warn("Failed to get memory percentile.");
+          })();
+        } else {
+          result.testcase = result.testcase.slice(1, -1).replace(/\\n/g, "\n");
+          that.printResult(result, "error", log_obj);
+          that.printResult(result, "testcase", log_obj);
+          that.printResult(result, "answer", log_obj);
+          that.printResult(result, "expected_answer", log_obj);
+          that.printResult(result, "stdout", log_obj);
+        }
+        reply.info(JSON.stringify(log_obj));
+        chainMgr.getChainHead().updateProblem(problem, {
+          state: result.ok ? "ac" : "notac",
+        });
+      });
+    });
+  }
+}
+
+export const submitApi: SubmitApi = new SubmitApi();
diff --git a/src/rpc/factory/api/testApi.ts b/src/rpc/factory/api/testApi.ts
new file mode 100644
index 0000000..3f351c1
--- /dev/null
+++ b/src/rpc/factory/api/testApi.ts
@@ -0,0 +1,200 @@
+/*
+ * Filename: /home/cc/vscode-leetcode-problem-rating/src/rpc/factory/api/testApi.ts
+ * Path: /home/cc/vscode-leetcode-problem-rating
+ * Created Date: Thursday, November 17th 2022, 11:44:14 am
+ * Author: ccagml
+ *
+ * Copyright (c) 2022 ccagml . All rights reserved.
+ */
+
+let _ = require("underscore");
+let lodash = require("lodash");
+
+import { storageUtils } from "../../utils/storageUtils";
+import { reply } from "../../utils/ReplyUtils";
+
+import { sessionUtils } from "../../utils/sessionUtils";
+import { ApiBase } from "../apiBase";
+import { commUtils } from "../../utils/commUtils";
+import { chainMgr } from "../../actionChain/chainManager";
+
+class TestApi extends ApiBase {
+  constructor() {
+    super();
+  }
+
+  callArg(argv) {
+    let argv_config = this.api_argv()
+      .option("i", {
+        alias: "interactive",
+        type: "boolean",
+        default: false,
+        describe: "Provide test case interactively",
+      })
+      .option("t", {
+        alias: "testcase",
+        type: "string",
+        default: "",
+        describe: "Provide test case",
+      })
+      .option("a", {
+        alias: "allcase",
+        type: "boolean",
+        default: false,
+        describe: "Provide all test case",
+      })
+      .positional("filename", {
+        type: "string",
+        default: "",
+        describe: "Code file to test",
+      });
+
+    argv_config.parseArgFromCmd(argv);
+
+    return argv_config.get_result();
+  }
+
+  printResult(actual, extra, k, log_obj) {
+    if (!actual.hasOwnProperty(k)) return;
+    // HACk: leetcode still return 'Accepted' even the answer is wrong!!
+    const v = actual[k] || "";
+    if (k === "state" && v === "Accepted") return;
+
+    // let ok = actual.ok;
+
+    const lines = Array.isArray(v) ? v : [v];
+    for (let line of lines) {
+      const extraInfo = extra ? ` (${extra})` : "";
+      if (k !== "state") {
+        let new_kk = lodash.startCase(k) + extraInfo;
+        if (!log_obj.hasOwnProperty(new_kk)) {
+          log_obj[new_kk] = [line];
+        } else {
+          log_obj[new_kk].push(line);
+        }
+      } else {
+        log_obj.messages.push(line);
+      }
+    }
+  }
+
+  runTest(argv) {
+    let that = this;
+    if (!storageUtils.exist(argv.filename)) return reply.fatal("File " + argv.filename + " not exist!");
+
+    const meta = storageUtils.meta(argv.filename);
+
+    // [key: string]: string[];
+    // messages: string[];
+
+    chainMgr.getChainHead().getProblem(meta, true, function (e, problem) {
+      if (e)
+        return reply.info(
+          JSON.stringify({
+            messages: ["error"],
+            code: [-1],
+            error: [e.msg || e],
+          })
+        );
+
+      if (!problem.testable)
+        return reply.info(
+          JSON.stringify({
+            messages: ["error"],
+            code: [-2],
+            error: ["not testable? please submit directly!"],
+          })
+        );
+
+      if (argv.testcase) {
+        problem.testcase = argv.testcase.replace(/\\n/g, "\n");
+      }
+
+      if (argv.allcase) {
+        let temp_test_set: Set = new Set();
+
+        let new_desc = problem.desc;
+        let calcCaseList = storageUtils.getAllCase(new_desc);
+        calcCaseList.forEach((x) => {
+          let xxx = x.join("\n");
+          temp_test_set.add(xxx);
+        });
+        if (meta.writeCase) {
+          meta.writeCase.forEach((xxx) => {
+            temp_test_set.add(xxx);
+          });
+        }
+
+        let temp_test: Array = [];
+        temp_test_set.forEach((x) => {
+          temp_test.push(x);
+        });
+
+        let all_case = temp_test.join("\n");
+        problem.testcase = all_case;
+      }
+
+      if (!problem.testcase)
+        return reply.info(
+          JSON.stringify({
+            messages: ["error"],
+            code: [-3],
+            error: ["missing testcase?"],
+          })
+        );
+
+      problem.file = argv.filename;
+      problem.lang = meta.lang;
+
+      chainMgr.getChainHead().testProblem(problem, function (e, results) {
+        if (e) return reply.info(JSON.stringify(e));
+
+        results = _.sortBy(results, (x) => x.type);
+
+        let log_obj: any = {};
+        log_obj.messages = [];
+        log_obj.system_message = {};
+        log_obj.system_message.fid = problem.fid;
+        log_obj.system_message.id = problem.id;
+        log_obj.system_message.qid = problem.id;
+        log_obj.system_message.sub_type = "test";
+        log_obj.system_message.accepted = false;
+
+        if (results[0].state === "Accepted") {
+          results[0].state = "Finished";
+          log_obj.system_message.accepted = true;
+        }
+        that.printResult(results[0], null, "state", log_obj);
+        that.printResult(results[0], null, "error", log_obj);
+
+        results[0].your_input = problem.testcase;
+        results[0].output = results[0].answer;
+        // LeetCode-CN returns the actual and expected answer into two separate responses
+        if (results[1]) {
+          results[0].expected_answer = results[1].answer;
+        }
+        results[0].stdout = results[0].stdout.slice(1, -1).replace(/\\n/g, "\n");
+        that.printResult(results[0], null, "your_input", log_obj);
+        that.printResult(results[0], results[0].runtime, "output", log_obj);
+        that.printResult(results[0], null, "expected_answer", log_obj);
+        that.printResult(results[0], null, "stdout", log_obj);
+        reply.info(JSON.stringify(log_obj));
+      });
+    });
+  }
+
+  call(argv) {
+    let that = this;
+    sessionUtils.argv = argv;
+    if (!argv.i) return that.runTest(argv);
+
+    commUtils.readStdin(function (e, data) {
+      if (e) return reply.info(e);
+
+      argv.testcase = data;
+      return that.runTest(argv);
+    });
+  }
+}
+
+export const testApi: TestApi = new TestApi();
diff --git a/src/rpc/factory/api/userApi.ts b/src/rpc/factory/api/userApi.ts
new file mode 100644
index 0000000..ab9a3d7
--- /dev/null
+++ b/src/rpc/factory/api/userApi.ts
@@ -0,0 +1,150 @@
+/*
+ * Filename: /home/cc/vscode-leetcode-problem-rating/src/rpc/factory/api/userApi.ts
+ * Path: /home/cc/vscode-leetcode-problem-rating
+ * Created Date: Thursday, November 17th 2022, 11:44:14 am
+ * Author: ccagml
+ *
+ * Copyright (c) 2022 ccagml . All rights reserved.
+ */
+
+let prompt_out = require("prompt");
+
+import { reply } from "../../utils/ReplyUtils";
+
+import { sessionUtils } from "../../utils/sessionUtils";
+import { ApiBase } from "../apiBase";
+
+import { chainMgr } from "../../actionChain/chainManager";
+
+class UserApi extends ApiBase {
+  constructor() {
+    super();
+  }
+
+  callArg(argv) {
+    let argv_config = this.api_argv()
+      .option("l", {
+        alias: "login",
+        type: "boolean",
+        default: false,
+        describe: "Login",
+      })
+      .option("c", {
+        alias: "cookie",
+        type: "boolean",
+        default: false,
+        describe: "cookieLogin",
+      })
+      .option("g", {
+        alias: "github",
+        type: "boolean",
+        default: false,
+        describe: "githubLogin",
+      })
+      .option("i", {
+        alias: "linkedin",
+        type: "boolean",
+        default: false,
+        describe: "linkedinLogin",
+      })
+      .option("L", {
+        alias: "logout",
+        type: "boolean",
+        default: false,
+        describe: "Logout",
+      });
+
+    argv_config.parseArgFromCmd(argv);
+
+    return argv_config.get_result();
+  }
+
+  call(argv) {
+    sessionUtils.argv = argv;
+    let user: any = null;
+    if (argv.login) {
+      // login
+      prompt_out.colors = false;
+      prompt_out.message = "";
+      prompt_out.start();
+      prompt_out.get(
+        [
+          { name: "login", required: true },
+          { name: "pass", required: true, hidden: true },
+        ],
+        function (e, user) {
+          if (e) {
+            return reply.info(JSON.stringify({ code: -1, msg: e.msg || e }));
+          }
+
+          chainMgr.getChainHead().login(user, function (e, user) {
+            if (e) {
+              return reply.info(JSON.stringify({ code: -2, msg: e.msg || e }));
+            }
+            reply.info(JSON.stringify({ code: 100, user_name: user.name }));
+          });
+        }
+      );
+    } else if (argv.logout) {
+      // logout
+      user = chainMgr.getChainHead().logout(user, true);
+      if (user) reply.info(JSON.stringify({ code: 100, user_name: user.name }));
+      else reply.info(JSON.stringify({ code: -3, msg: "You are not login yet?" }));
+      // third parties
+    } else if (argv.github || argv.linkedin) {
+      // add future third parties here
+      const functionMap = new Map([
+        ["g", chainMgr.getChainHead().githubLogin],
+        ["github", chainMgr.getChainHead().githubLogin],
+        ["i", chainMgr.getChainHead().linkedinLogin],
+        ["linkedin", chainMgr.getChainHead().linkedinLogin],
+      ]);
+      const keyword = Object.entries(argv).filter((i) => i[1] === true)[0][0];
+      const coreFunction = functionMap.get(keyword);
+      if (coreFunction) {
+        prompt_out.colors = false;
+        prompt_out.message = "";
+        prompt_out.start();
+        prompt_out.get(
+          [
+            { name: "login", required: true },
+            { name: "pass", required: true, hidden: true },
+          ],
+          function (e, user) {
+            if (e) return reply.info(JSON.stringify({ code: -4, msg: e.msg || e }));
+            coreFunction(user, function (e, user) {
+              if (e) return reply.info(JSON.stringify({ code: -5, msg: e.msg || e }));
+              reply.info(JSON.stringify({ code: 100, user_name: user.name }));
+            });
+          }
+        );
+      }
+    } else if (argv.cookie) {
+      // session
+      prompt_out.colors = false;
+      prompt_out.message = "";
+      prompt_out.start();
+      prompt_out.get(
+        [
+          { name: "login", required: true },
+          { name: "cookie", required: true },
+        ],
+        function (e, user) {
+          if (e) return reply.info(e);
+          chainMgr.getChainHead().cookieLogin(user, function (e, user) {
+            if (e) return reply.info(JSON.stringify({ code: -6, msg: e.msg || e }));
+            reply.info(JSON.stringify({ code: 100, user_name: user.name }));
+          });
+        }
+      );
+    } else {
+      // show current user
+      user = sessionUtils.getUser();
+      if (user) {
+        reply.info(JSON.stringify({ code: 100, user_name: user.name }));
+      } else return reply.info(JSON.stringify({ code: -7, msg: "You are not login yet?" }));
+    }
+  }
+}
+
+export const userApi: UserApi = new UserApi();
diff --git a/src/rpc/factory/apiBase.ts b/src/rpc/factory/apiBase.ts
new file mode 100644
index 0000000..7b22632
--- /dev/null
+++ b/src/rpc/factory/apiBase.ts
@@ -0,0 +1,97 @@
+/*
+ * Filename: /home/cc/vscode-leetcode-problem-rating/src/rpc/factory/apiBase.ts
+ * Path: /home/cc/vscode-leetcode-problem-rating
+ * Created Date: Thursday, November 17th 2022, 11:44:14 am
+ * Author: ccagml
+ *
+ * Copyright (c) 2022 ccagml . All rights reserved.
+ */
+
+export interface IApi {
+  callArg(arg);
+  call(arg): void;
+}
+
+export class ApiBase implements IApi {
+  constructor() {}
+  callArg(arg: any) {
+    console.log("未实现callArg", arg);
+  }
+  call(arg: any) {
+    console.log("未实现call", arg);
+  }
+  api_argv() {
+    let base = {
+      all_base_data: {},
+      positional_index: 0,
+      positional_key: {},
+      option: function (key, value) {
+        this.all_base_data[key] = value.default;
+        this.all_base_data[value.alias] = value.default;
+        this[key] = value;
+        return this;
+      },
+      positional: function (key, value) {
+        this.positional_key[this.positional_index] = key;
+        this.positional_index = this.positional_index + 1;
+        this.all_base_data[key] = value.default;
+        this.all_base_data[value.alias] = value.default;
+        this[key] = value;
+        return this;
+      },
+      set_opt(key, temp_val?) {
+        let cfg = this[key];
+        if (cfg) {
+          if (cfg.type == "boolean") {
+            this.all_base_data[key] = true;
+            if (cfg.alias) {
+              this.all_base_data[cfg.alias] = true;
+            }
+            return false;
+          } else {
+            this.all_base_data[key] = temp_val;
+            if (cfg.alias) {
+              this.all_base_data[cfg.alias] = temp_val;
+            }
+            return true;
+          }
+        } else {
+          this.all_base_data[key] = true;
+        }
+        return false;
+      },
+      set_posi(value, index) {
+        let cfg_key = this.positional_key[index];
+        let cfg = this[cfg_key];
+        if (cfg) {
+          this.all_base_data[cfg_key] = value;
+          if (cfg.alias) {
+            this.all_base_data[cfg.alias] = value;
+          }
+        }
+      },
+      parseArgFromCmd(argv) {
+        let all_posi = 0;
+        for (let index = 3; index < argv.length; index++) {
+          let con = argv[index];
+          if (con[0] == "-" && con[1] == "-") {
+            this.set_opt(con.substring(2));
+          } else if (con[0] == "-") {
+            for (let con_index = 1; con_index < con.length; con_index++) {
+              if (this.set_opt(con[con_index], argv[index + 1])) {
+                con_index++;
+              }
+            }
+          } else {
+            this.set_posi(con, all_posi);
+            all_posi = all_posi + 1;
+          }
+        }
+      },
+      get_result: function () {
+        return this.all_base_data;
+      },
+    };
+    return base;
+  }
+}
diff --git a/src/rpc/factory/apiFactory.ts b/src/rpc/factory/apiFactory.ts
new file mode 100644
index 0000000..065defe
--- /dev/null
+++ b/src/rpc/factory/apiFactory.ts
@@ -0,0 +1,37 @@
+import { cacheApi } from "./api/cacheApi";
+import { listApi } from "./api/listApi";
+import { pluginApi } from "./api/pluginApi";
+import { queryApi } from "./api/queryApi";
+import { showApi } from "./api/showApi";
+import { starApi } from "./api/starApi";
+import { submitApi } from "./api/submitApi";
+import { testApi } from "./api/testApi";
+import { userApi } from "./api/userApi";
+import { IApi } from "./apiBase";
+
+class ApiFactory {
+  constructor() {}
+  getApi(api: string): IApi | undefined {
+    if (api == "cache") {
+      return cacheApi;
+    } else if (api == "list") {
+      return listApi;
+    } else if (api == "plugin") {
+      return pluginApi;
+    } else if (api == "query") {
+      return queryApi;
+    } else if (api == "show") {
+      return showApi;
+    } else if (api == "star") {
+      return starApi;
+    } else if (api == "submit") {
+      return submitApi;
+    } else if (api == "test") {
+      return testApi;
+    } else if (api == "user") {
+      return userApi;
+    }
+    return undefined;
+  }
+}
+export const apiFactory: ApiFactory = new ApiFactory();
diff --git a/src/rpc/utils/ReplyUtils.ts b/src/rpc/utils/ReplyUtils.ts
new file mode 100644
index 0000000..aca9f6e
--- /dev/null
+++ b/src/rpc/utils/ReplyUtils.ts
@@ -0,0 +1,62 @@
+/*
+ * Filename: /home/cc/vscode-leetcode-problem-rating/src/rpc/Response.ts
+ * Path: /home/cc/vscode-leetcode-problem-rating
+ * Created Date: Monday, November 14th 2022, 4:04:31 pm
+ * Author: ccagml
+ *
+ * Copyright (c) 2022 ccagml . All rights reserved.
+ */
+
+let _ = require("underscore");
+
+class Reply {
+  output = _.bind(console.log, console);
+  level: any;
+  levels = new Map([
+    ["INFO", { value: 2 }],
+    ["WARN", { value: 3 }],
+    ["ERROR", { value: 4 }],
+  ]);
+  setLevel(name: any) {
+    this.level = this.levels.get(name) || this.levels.get("INFO");
+  }
+
+  fail(e: any) {
+    let msg = e.msg || e;
+    if (e.statusCode) {
+      msg += " [code=" + e.statusCode + "]";
+    }
+    this.error(msg);
+  }
+
+  fatal(e: any) {
+    this.error(e);
+    process.exit(1);
+  }
+
+  init() {
+    this.setLevel("INFO");
+  }
+
+  info(...rest: any[]) {
+    const args = rest; //Array.from(arguments);
+    let s = args.map((x) => x.toString()).join(" ");
+    this.output(s);
+  }
+  warn(...rest: any[]) {
+    const args = rest; //Array.from(arguments);
+    args.unshift("[" + "warn" + "]");
+
+    let s = args.map((x) => x.toString()).join(" ");
+    this.output(s);
+  }
+  error(...rest: any[]) {
+    const args = rest; //Array.from(arguments);
+    args.unshift("[" + "error" + "]");
+
+    let s = args.map((x) => x.toString()).join(" ");
+    this.output(s);
+  }
+}
+
+export const reply: Reply = new Reply();
diff --git a/src/rpc/utils/commUtils.ts b/src/rpc/utils/commUtils.ts
new file mode 100644
index 0000000..d895b3c
--- /dev/null
+++ b/src/rpc/utils/commUtils.ts
@@ -0,0 +1,86 @@
+/*
+ * Filename: /home/cc/vscode-leetcode-problem-rating/src/rpc/commUtils.ts
+ * Path: /home/cc/vscode-leetcode-problem-rating
+ * Created Date: Wednesday, November 16th 2022, 4:50:55 pm
+ * Author: ccagml
+ *
+ * Copyright (c) 2022 ccagml . All rights reserved.
+ */
+
+import { storageUtils } from "./storageUtils";
+
+class CommUtils {
+  KEYS;
+  constructor() {
+    this.KEYS = {
+      user: "../user",
+      stat: "../stat",
+      plugins: "../../plugins",
+      problems: "problems",
+      translation: "translationConfig",
+      ranting_path: "../../rating",
+      problem: (p) => p.fid + "." + p.slug + "." + p.category,
+    };
+  }
+
+  getNameByLevel(level: any) {
+    switch (level) {
+      case 1:
+        return "Easy";
+      case 2:
+        return "Medium";
+      case 3:
+        return "Hard";
+      default:
+        return " ";
+    }
+  }
+
+  readStdin(cb) {
+    const stdin = process.stdin;
+    let bufs: Array = [];
+
+    console.log(
+      "NOTE: to finish the input, press " + (storageUtils.isWindows() ? " and " : "")
+    );
+
+    stdin.on("readable", function () {
+      const data = stdin.read();
+      if (data) {
+        // windows doesn't treat ctrl-D as EOF
+        if (storageUtils.isWindows() && data.toString() === "\x04\r\n") {
+          stdin.emit("end");
+        } else {
+          bufs.push(data);
+        }
+      }
+    });
+    stdin.on("end", function () {
+      cb(null, Buffer.concat(bufs).toString());
+    });
+    stdin.on("error", cb);
+  }
+
+  getSetCookieValue(resp: any, key: any) {
+    const cookies = resp.headers["set-cookie"];
+    if (!cookies) return null;
+
+    for (let i = 0; i < cookies.length; ++i) {
+      const sections = cookies[i].split(";");
+      for (let j = 0; j < sections.length; ++j) {
+        const kv = sections[j].trim().split("=");
+        if (kv[0] === key) return kv[1];
+      }
+    }
+    return null;
+  }
+
+  printSafeHTTP(msg: any) {
+    return msg
+      .replace(/(Cookie\s*:\s*)'.*?'/, "$1")
+      .replace(/('X-CSRFToken'\s*:\s*)'.*?'/, "$1")
+      .replace(/('set-cookie'\s*:\s*)\[.*?\]/, "$1");
+  }
+}
+
+export const commUtils: CommUtils = new CommUtils();
diff --git a/src/rpc/utils/configUtils.ts b/src/rpc/utils/configUtils.ts
new file mode 100644
index 0000000..6c829a9
--- /dev/null
+++ b/src/rpc/utils/configUtils.ts
@@ -0,0 +1,140 @@
+/*
+ * Filename: https://github.com/ccagml/vscode-leetcode-problem-rating/src/rpc/config.ts
+ * Path: https://github.com/ccagml/vscode-leetcode-problem-rating
+ * Created Date: Thursday, October 27th 2022, 7:43:29 pm
+ * Author: ccagml
+ *
+ * Copyright (c) 2022 ccagml . All rights reserved.
+ */
+
+let underscore = require("underscore");
+
+class Config {
+  LCPTCTX: any;
+  app: any;
+  sys: any;
+  autologin: any;
+  code: any;
+  file: any;
+  color: any;
+  icon: any;
+  network: any;
+  plugins: any;
+  constructor() {
+    this.sys = {
+      categories: ["algorithms", "LCCI", "LCOF", "LCOF2"],
+      langs: [
+        "bash",
+        "c",
+        "cpp",
+        "csharp",
+        "golang",
+        "java",
+        "javascript",
+        "kotlin",
+        "mysql",
+        "php",
+        "python",
+        "python3",
+        "ruby",
+        "rust",
+        "scala",
+        "swift",
+        "typescript",
+      ],
+      urls: {
+        // base urls
+        base: "https://leetcode.com",
+        graphql: "https://leetcode.com/graphql",
+        login: "https://leetcode.com/accounts/login/",
+        // third part login base urls. TODO facebook google
+        github_login: "https://leetcode.com/accounts/github/login/?next=%2F",
+        facebook_login: "https://leetcode.com/accounts/facebook/login/?next=%2F",
+        linkedin_login: "https://leetcode.com/accounts/linkedin_oauth2/login/?next=%2F",
+        // redirect urls
+        leetcode_redirect: "https://leetcode.com/",
+        github_tf_redirect: "https://github.com/sessions/two-factor",
+        // simulate login urls
+        github_login_request: "https://github.com/login",
+        github_session_request: "https://github.com/session",
+        github_tf_session_request: "https://github.com/sessions/two-factor",
+        linkedin_login_request: "https://www.linkedin.com/login",
+        linkedin_session_request: "https://www.linkedin.com/checkpoint/lg/login-submit",
+        // questions urls
+        problems: "https://leetcode.com/api/problems/$category/",
+        problem: "https://leetcode.com/problems/$slug/description/",
+        test: "https://leetcode.com/problems/$slug/interpret_solution/",
+        session: "https://leetcode.com/session/",
+        submit: "https://leetcode.com/problems/$slug/submit/",
+        submissions: "https://leetcode.com/api/submissions/$slug",
+        submission: "https://leetcode.com/submissions/detail/$id/",
+        verify: "https://leetcode.com/submissions/detail/$id/check/",
+        favorites: "https://leetcode.com/list/api/questions",
+        favorite_delete: "https://leetcode.com/list/api/questions/$hash/$id",
+        problem_detail: "",
+        noj_go: "",
+        u: "",
+      },
+    };
+
+    this.autologin = {
+      enable: false,
+      retry: 2,
+    };
+    this.code = {
+      editor: "vim",
+      lang: "cpp",
+    };
+    this.file = {
+      show: "${fid}.${slug}",
+      submission: "${fid}.${slug}.${sid}.${ac}",
+    };
+    this.color = {
+      enable: true,
+      theme: "default",
+    };
+    this.icon = {
+      theme: "",
+    };
+    this.network = {
+      concurrency: 10,
+      delay: 1,
+    };
+    this.plugins = {};
+  }
+
+  init(ctx) {
+    this.LCPTCTX = ctx;
+  }
+
+  getAll(useronly) {
+    const cfg = underscore.extendOwn({}, this);
+    if (useronly) delete cfg.sys;
+    return cfg;
+  }
+
+  fix_cn() {
+    this.app = "leetcode.cn";
+    this.sys.urls.base = "https://leetcode.cn";
+    this.sys.urls.login = "https://leetcode.cn/accounts/login/";
+    this.sys.urls.problems = "https://leetcode.cn/api/problems/$category/";
+    this.sys.urls.problem = "https://leetcode.cn/problems/$slug/description/";
+    this.sys.urls.graphql = "https://leetcode.cn/graphql";
+    this.sys.urls.problem_detail = "https://leetcode.cn/graphql";
+    this.sys.urls.test = "https://leetcode.cn/problems/$slug/interpret_solution/";
+    this.sys.urls.session = "https://leetcode.cn/session/";
+    this.sys.urls.submit = "https://leetcode.cn/problems/$slug/submit/";
+    this.sys.urls.submissions = "https://leetcode.cn/api/submissions/$slug";
+    this.sys.urls.submission = "https://leetcode.cn/submissions/detail/$id/";
+    this.sys.urls.verify = "https://leetcode.cn/submissions/detail/$id/check/";
+    this.sys.urls.favorites = "https://leetcode.cn/list/api/questions";
+    this.sys.urls.favorite_delete = "https://leetcode.cn/list/api/questions/$hash/$id";
+    this.sys.urls.noj_go = "https://leetcode.cn/graphql/noj-go/";
+    this.sys.urls.u = "https://leetcode.cn/u/$username/";
+    this.sys.urls.github_login = "https://leetcode.cn/accounts/github/login/?next=%2F";
+    this.sys.urls.linkedin_login = "https://leetcode.cn/accounts/linkedin_oauth2/login/?next=%2F";
+    this.sys.urls.leetcode_redirect = "https://leetcode.cn/";
+  }
+}
+
+export const configUtils: Config = new Config();
diff --git a/src/childProcessCall/queue.ts b/src/rpc/utils/queueUtils.ts
similarity index 71%
rename from src/childProcessCall/queue.ts
rename to src/rpc/utils/queueUtils.ts
index 1db7165..3ff2496 100644
--- a/src/childProcessCall/queue.ts
+++ b/src/rpc/utils/queueUtils.ts
@@ -1,5 +1,5 @@
 /*
- * Filename: https://github.com/ccagml/vscode-leetcode-problem-rating/src/childProcessCall/queue.ts
+ * Filename: https://github.com/ccagml/vscode-leetcode-problem-rating/src/rpc/queue.ts
  * Path: https://github.com/ccagml/vscode-leetcode-problem-rating
  * Created Date: Thursday, October 27th 2022, 7:43:29 pm
  * Author: ccagml
@@ -7,11 +7,9 @@
  * Copyright (c) 2022 ccagml . All rights reserved.
  */
 
+let underscore = require("underscore");
 
-
-let underscore = require('underscore');
-
-import { config } from "./config";
+import { configUtils } from "./configUtils";
 
 export class Queue {
   tasks;
@@ -30,28 +28,29 @@ export class Queue {
   addTask(task) {
     this.tasks.push(task);
     return this;
-  };
+  }
 
   addTasks(tasks) {
     this.tasks = this.tasks.concat(tasks);
     return this;
-  };
+  }
 
   run(concurrency?, onDone?) {
-    this.concurrency = concurrency || config.network.concurrency || 1;
+    this.concurrency = concurrency || configUtils.network.concurrency || 1;
     this.onDone = onDone;
 
     const self = this;
     for (let i = 0; i < this.concurrency; ++i) {
-      setImmediate(function () { self.workerRun(); });
+      setImmediate(function () {
+        self.workerRun();
+      });
     }
-  };
+  }
 
   workerRun() {
     // no more tasks, quit now
     if (this.tasks.length === 0) {
-      if (--this.concurrency === 0 && this.onDone)
-        this.onDone(this.error, this.ctx);
+      if (--this.concurrency === 0 && this.onDone) this.onDone(this.error, this.ctx);
       return;
     }
 
@@ -61,8 +60,9 @@ export class Queue {
       if (e) self.error = e;
 
       // TODO: could retry failed task here.
-      setImmediate(function () { self.workerRun(); });
+      setImmediate(function () {
+        self.workerRun();
+      });
     });
-  };
+  }
 }
-
diff --git a/src/childProcessCall/session.ts b/src/rpc/utils/sessionUtils.ts
similarity index 52%
rename from src/childProcessCall/session.ts
rename to src/rpc/utils/sessionUtils.ts
index d1737c3..bd30d67 100644
--- a/src/childProcessCall/session.ts
+++ b/src/rpc/utils/sessionUtils.ts
@@ -1,5 +1,5 @@
 /*
- * Filename: https://github.com/ccagml/vscode-leetcode-problem-rating/src/childProcessCall/session.ts
+ * Filename: https://github.com/ccagml/vscode-leetcode-problem-rating/src/rpc/session.ts
  * Path: https://github.com/ccagml/vscode-leetcode-problem-rating
  * Created Date: Thursday, October 27th 2022, 7:43:29 pm
  * Author: ccagml
@@ -7,62 +7,59 @@
  * Copyright (c) 2022 ccagml . All rights reserved.
  */
 
-
-let moment_out = require('moment');
-let underscore = require('underscore');
-
+let moment_out = require("moment");
+let underscore = require("underscore");
 
 import { storageUtils } from "./storageUtils";
-import { config } from "./config";
-import { helper } from "./helper";
+import { configUtils } from "./configUtils";
+import { commUtils } from "./commUtils";
 
 class Session {
   errors = {
     EXPIRED: {
-      msg: 'session expired, please login again',
-      statusCode: -1
-    }
+      msg: "session expired, please login again",
+      statusCode: -1,
+    },
   };
   argv: any = {};
-  constructor() {
-  }
+  constructor() {}
   public getUser = function () {
-    return storageUtils.getCache(helper.KEYS.user);
+    return storageUtils.getCache(commUtils.KEYS.user);
   };
 
   public saveUser = function (user) {
     // when auto login enabled, have to save password to re-login later
     // otherwise don't dump password for the sake of security.
-    const _user = underscore.omit(user, config.autologin.enable ? [] : ['pass']);
-    storageUtils.setCache(helper.KEYS.user, _user);
+    const _user = underscore.omit(user, configUtils.autologin.enable ? [] : ["pass"]);
+    storageUtils.setCache(commUtils.KEYS.user, _user);
   };
 
   public deleteUser = function () {
-    storageUtils.delCache(helper.KEYS.user);
+    storageUtils.delCache(commUtils.KEYS.user);
   };
 
   public deleteCodingSession = function () {
-    storageUtils.delCache(helper.KEYS.problems);
+    storageUtils.delCache(commUtils.KEYS.problems);
   };
 
   public isLogin() {
     return this.getUser() !== null;
-  };
+  }
 
   public updateStat = function (k, v) {
     // TODO: use other storage if too many stat data
-    const today = moment_out().format('YYYY-MM-DD');
-    const stats = storageUtils.getCache(helper.KEYS.stat) || {};
-    const stat = stats[today] = stats[today] || {};
+    const today = moment_out().format("YYYY-MM-DD");
+    const stats = storageUtils.getCache(commUtils.KEYS.stat) || {};
+    const stat = (stats[today] = stats[today] || {});
 
-    if (k.endsWith('.set')) {
+    if (k.endsWith(".set")) {
       const s = new Set(stat[k] || []);
       s.add(v);
       stat[k] = Array.from(s);
     } else {
       stat[k] = (stat[k] || 0) + v;
     }
-    storageUtils.setCache(helper.KEYS.stat, stats);
+    storageUtils.setCache(commUtils.KEYS.stat, stats);
   };
 }
-export const session: Session = new Session();
+export const sessionUtils: Session = new Session();
diff --git a/src/rpc/utils/storageUtils.ts b/src/rpc/utils/storageUtils.ts
new file mode 100644
index 0000000..19ac433
--- /dev/null
+++ b/src/rpc/utils/storageUtils.ts
@@ -0,0 +1,486 @@
+/*
+ * Filename: https://github.com/ccagml/vscode-leetcode-problem-rating/src/rpc/storageUtils.ts
+ * Path: https://github.com/ccagml/vscode-leetcode-problem-rating
+ * Created Date: Thursday, October 27th 2022, 7:43:29 pm
+ * Author: ccagml
+ *
+ * Copyright (c) 2022 ccagml . All rights reserved.
+ */
+
+let fs = require("fs");
+let os = require("os");
+let path = require("path");
+
+let _ = require("underscore");
+let mkdirp = require("mkdirp");
+
+export interface IMETA {
+  id: string;
+  fid: string;
+  lang: string;
+  writeCase: Array;
+}
+
+//Object.assign({}, defaultMETA, {})
+export const defaultMETA: IMETA = {
+  id: "",
+  fid: "",
+  lang: "",
+  writeCase: [],
+};
+
+class StorageUtils {
+  public storageFileInfo = {
+    bash: {
+      ext: ".sh",
+      start: "#",
+      line: "#",
+      end: "#",
+      singleLine: "#",
+    },
+    c: {
+      ext: ".c",
+      start: "/*",
+      line: " *",
+      end: " */",
+      singleLine: "//",
+    },
+    cpp: {
+      ext: ".cpp",
+      start: "/*",
+      line: " *",
+      end: " */",
+      singleLine: "//",
+    },
+    csharp: {
+      ext: ".cs",
+      start: "/*",
+      line: " *",
+      end: " */",
+      singleLine: "//",
+    },
+    golang: {
+      ext: ".go",
+      start: "/*",
+      line: " *",
+      end: " */",
+      singleLine: "//",
+    },
+    java: {
+      ext: ".java",
+      start: "/*",
+      line: " *",
+      end: " */",
+      singleLine: "//",
+    },
+    javascript: {
+      ext: ".js",
+      start: "/*",
+      line: " *",
+      end: " */",
+      singleLine: "//",
+    },
+    kotlin: {
+      ext: ".kt",
+      start: "/*",
+      line: " *",
+      end: " */",
+      singleLine: "//",
+    },
+    mysql: {
+      ext: ".sql",
+      start: "--",
+      line: "--",
+      end: "--",
+      singleLine: "--",
+    },
+    php: {
+      ext: ".php",
+      start: "/*",
+      line: " *",
+      end: " */",
+      singleLine: "//",
+    },
+    python: {
+      ext: ".py",
+      start: "#",
+      line: "#",
+      end: "#",
+      singleLine: "#",
+    },
+    python3: {
+      ext: ".py",
+      start: "#",
+      line: "#",
+      end: "#",
+      singleLine: "#",
+    },
+    ruby: {
+      ext: ".rb",
+      start: "#",
+      line: "#",
+      end: "#",
+      singleLine: "#",
+    },
+    rust: {
+      ext: ".rs",
+      start: "/*",
+      line: " *",
+      end: " */",
+      singleLine: "//",
+    },
+    scala: {
+      ext: ".scala",
+      start: "/*",
+      line: " *",
+      end: " */",
+      singleLine: "//",
+    },
+    swift: {
+      ext: ".swift",
+      start: "/*",
+      line: " *",
+      end: " */",
+      singleLine: "//",
+    },
+    typescript: {
+      ext: ".ts",
+      start: "/*",
+      line: " *",
+      end: " */",
+      singleLine: "//",
+    },
+  };
+
+  getFileExtByLanguage(lang) {
+    const res = this.storageFileInfo[lang];
+    return res ? res.ext : ".raw";
+  }
+
+  getCommentStyleByLanguage(lang) {
+    const res = this.storageFileInfo[lang];
+    return res;
+  }
+
+  public init() {
+    this.mkdir(this.homeDir());
+    this.initCache();
+  }
+
+  public isWindows() {
+    return process.platform === "win32";
+  }
+
+  public userHomeDir() {
+    return process.env.HOME || process.env.USERPROFILE;
+  }
+
+  public homeDir() {
+    return path.join(this.userHomeDir(), ".lcpr");
+  }
+
+  public appDir() {
+    const config = require("./configUtils");
+    return path.join(this.homeDir(), config.app || "leetcode");
+  }
+
+  // 缓存目录
+  public cacheDir() {
+    return path.join(this.appDir(), "cache");
+  }
+
+  // 代码目录
+  public codeDir(dir) {
+    return path.join(__dirname, dir || "");
+  }
+
+  // 缓存目录文件
+  public cacheFile(k) {
+    return path.join(this.cacheDir(), k + ".json");
+  }
+
+  // public configFile() {
+  //   return path.join(this.homeDir(), 'config.json');
+  // };
+
+  // 插件代码目录
+  public listCodeDir(dir) {
+    dir = this.codeDir(dir);
+    let that = this;
+    return this.list(dir).map(function (f) {
+      const fullpath = path.join(dir, f);
+      const ext = path.extname(f);
+      const name = path.basename(f, ext);
+
+      let data = null;
+      switch (ext) {
+        case ".js":
+          data = require(fullpath).pluginObj;
+          break;
+        case ".json":
+          data = JSON.parse(that.getData(fullpath));
+          break;
+      }
+      return { name: name, data: data, file: f };
+    });
+  }
+
+  public initCache() {
+    this.mkdir(this.cacheDir());
+  }
+  public deleteAllCache() {
+    this.listCache().forEach((value) => {
+      this.delCache(value.name);
+    });
+  }
+
+  public getCache(k) {
+    const fullpath = this.cacheFile(k);
+    if (!this.exist(fullpath)) return null;
+
+    return JSON.parse(this.getData(fullpath));
+  }
+
+  public setCache(k, v) {
+    const fullpath = this.cacheFile(k);
+    this.write(fullpath, JSON.stringify(v));
+    return true;
+  }
+
+  public delCache(k) {
+    const fullpath = this.cacheFile(k);
+    if (!this.exist(fullpath)) return false;
+
+    this.rm(fullpath);
+    return true;
+  }
+
+  public listCache(): Array {
+    let that = this;
+    return this.list(this.cacheDir())
+      .filter((x) => path.extname(x) === ".json")
+      .map(function (filename) {
+        const k = path.basename(filename, ".json");
+        const stat = that.stat(that.cacheFile(k));
+        return {
+          name: k,
+          size: stat.size,
+          mtime: stat.mtime,
+        };
+      });
+  }
+
+  public mkdir(fullpath) {
+    if (fs.existsSync(fullpath)) return;
+    mkdirp.sync(fullpath);
+  }
+
+  public exist(fullpath) {
+    return fs.existsSync(fullpath);
+  }
+
+  public rm(fullpath) {
+    return fs.unlinkSync(fullpath);
+  }
+
+  public mv(src, dst) {
+    return fs.renameSync(src, dst);
+  }
+
+  public list(dir) {
+    return fs.readdirSync(dir);
+  }
+
+  public stat(fullpath) {
+    return fs.statSync(fullpath);
+  }
+
+  public write(fullpath, data) {
+    return fs.writeFileSync(fullpath, data);
+  }
+
+  public name(fullpath) {
+    return path.basename(fullpath, path.extname(fullpath));
+  }
+
+  public getData(fullpath) {
+    return fs.existsSync(fullpath) ? fs.readFileSync(fullpath).toString() : null;
+  }
+
+  // 获取要提交测试的数据
+  public codeData(fullpath) {
+    const data = this.getData(fullpath);
+
+    if (data === null) {
+      return null;
+    }
+
+    const lines = data.split(/\r\n|\n|\r/);
+    const start = lines.findIndex((x) => x.indexOf("@lc code=start") !== -1);
+    const end = lines.findIndex((x) => x.indexOf("@lc code=end") !== -1);
+
+    if (start !== -1 && end !== -1 && start + 1 <= end) {
+      return lines.slice(start + 1, end).join(os.EOL);
+    }
+
+    return data;
+  }
+
+  /**
+   * name
+   */
+  public getAllCase(a_desc) {
+    let new_desc = a_desc.replace(/<\/sup>/gm, "").replace(//gm, "^");
+    new_desc = require("he").decode(require("cheerio").load(new_desc).root().text());
+    // NOTE: wordwrap internally uses '\n' as EOL, so here we have to
+    // remove all '\r' in the raw string.
+    new_desc = new_desc.replace(/\r\n/g, "\n").replace(/^ /gm, "");
+    let input = require("wordwrap")(120)(new_desc).split("\n");
+    let temp_test: Array = [];
+    let start_flag = false;
+    let temp_collect = "";
+    for (let all_input = 0; all_input < input.length; all_input++) {
+      const element = input[all_input];
+      let check_index = element.indexOf("输入:");
+
+      if (check_index == -1) {
+        check_index = element.indexOf("输入:");
+      }
+
+      if (check_index == -1) {
+        check_index = element.indexOf("Input:");
+      }
+      if (check_index != -1) {
+        temp_collect += element.substring(check_index + 1);
+        start_flag = true;
+        continue;
+      }
+      check_index = element.indexOf("输出:");
+      if (check_index == -1) {
+        check_index = element.indexOf("输出:");
+      }
+      if (check_index == -1) {
+        check_index = element.indexOf("Output:");
+      }
+      if (check_index != -1) {
+        start_flag = false;
+      }
+      if (start_flag) {
+        temp_collect += element;
+      } else {
+        if (temp_collect.length > 0) {
+          let new_ele = temp_collect;
+          let temp_case: Array = [];
+          let wait_cur = "";
+          let no_need_flag = false;
+          for (let index = new_ele.length - 1; index >= 0; index--) {
+            if (no_need_flag) {
+              if (new_ele[index] == ",") {
+                no_need_flag = false;
+              }
+            } else {
+              if (new_ele[index] == "=") {
+                temp_case.push(wait_cur.trim());
+                no_need_flag = true;
+                wait_cur = "";
+              } else {
+                wait_cur = new_ele[index] + wait_cur;
+              }
+            }
+          }
+          let new_temp_case: Array = [];
+          for (let tci = temp_case.length - 1; tci >= 0; tci--) {
+            new_temp_case.push(temp_case[tci]);
+          }
+          temp_test.push(new_temp_case);
+          temp_collect = "";
+        }
+      }
+    }
+
+    return temp_test;
+  }
+
+  // 加载输出模板数据
+  public render(tpl, data) {
+    const tplfile = path.join(__dirname, "..", "..", "..", "..", "resources", "templates", tpl + ".tpl");
+    let result = _.template(this.getData(tplfile).replace(/\r\n/g, "\n"))(data);
+    if (this.isWindows()) {
+      result = result.replace(/\n/g, "\r\n");
+    } else {
+      result = result.replace(/\r\n/g, "\n");
+    }
+    return result;
+  }
+
+  public fmt(format, data) {
+    return _.template(format)(data);
+  }
+
+  // 去掉头尾的\n
+  public deleteWriteCaseHeadENDn(testCase) {
+    if (testCase.length < 3) {
+      return testCase;
+    }
+    let start = 0;
+    let end = testCase.length - 1;
+    let flag = false;
+    while (start < end - 1 && testCase[start] == "\n") {
+      start++;
+      flag = true;
+    }
+    while (end >= 1 && testCase[end] == "\n") {
+      end--;
+      flag = true;
+    }
+    if (flag) {
+      return testCase.substring(start, end + 1);
+    }
+    return testCase;
+  }
+
+  public meta(filename) {
+    const m = Object.assign({}, defaultMETA, {});
+
+    let file_info = this.getData(filename).split("\n");
+
+    let temp_test: Array = [];
+    let caseFlag: boolean = false;
+    let curCase = "";
+
+    for (let all_input = 0; all_input < file_info.length; all_input++) {
+      const lineContent = file_info[all_input];
+      if (caseFlag && lineContent.indexOf("@lcpr case=end") < 0) {
+        curCase += lineContent
+          .replace(/#/g, "")
+          .replace(/\/\//g, "")
+          .replace(/--/g, "")
+          .replace(/\s+/g, "")
+          .replace(/\\n/g, "\n");
+      }
+      // 收集所有用例
+      if (lineContent.indexOf("@lcpr case=start") >= 0) {
+        caseFlag = true;
+      }
+      if (caseFlag && lineContent.indexOf("@lcpr case=end") >= 0) {
+        temp_test.push(this.deleteWriteCaseHeadENDn(curCase));
+        curCase = "";
+        caseFlag = false;
+      }
+      if (lineContent.indexOf(" @lc app=") >= 0) {
+        // @lc app=leetcode.cn id=剑指 Offer II 116 lang=cpp
+        let id_right = lineContent.split("id=")[1];
+        let lang_cat = id_right.split("lang=");
+        let id = lang_cat[0].trim();
+        let lang = lang_cat[1].trim();
+        m.id = id;
+        m.fid = id;
+        m.lang = lang;
+      }
+      m.writeCase = temp_test;
+    }
+    return m;
+  }
+}
+
+export const storageUtils: StorageUtils = new StorageUtils();
diff --git a/src/service/BaseWebviewService.ts b/src/service/BaseWebviewService.ts
index 3646604..7345d28 100644
--- a/src/service/BaseWebviewService.ts
+++ b/src/service/BaseWebviewService.ts
@@ -7,7 +7,6 @@
  * Copyright (c) 2022 ccagml . All rights reserved.
  */
 
-
 import { commands, ConfigurationChangeEvent, Disposable, ViewColumn, WebviewPanel, window, workspace } from "vscode";
 import { markdownService } from "./MarkdownService";
 import { IWebViewOption } from "../model/Model";
@@ -15,72 +14,77 @@ import { openSettingsEditor } from "../utils/ConfigUtils";
 import { promptHintMessage } from "../utils/OutputUtils";
 
 export abstract class BaseWebViewService implements Disposable {
+  protected readonly viewType: string = "leetcode.webview";
+  protected panel: WebviewPanel | undefined;
+  private listeners: Disposable[] = [];
 
-    protected readonly viewType: string = "leetcode.webview";
-    protected panel: WebviewPanel | undefined;
-    private listeners: Disposable[] = [];
-
-    public dispose(): void {
-        if (this.panel) {
-            this.panel.dispose();
-        }
+  public dispose(): void {
+    if (this.panel) {
+      this.panel.dispose();
     }
+  }
 
-    protected showWebviewInternal(): void {
-        const { title, viewColumn, preserveFocus } = this.getWebviewOption();
-        if (!this.panel) {
-            this.panel = window.createWebviewPanel(this.viewType, title, { viewColumn, preserveFocus }, {
-                enableScripts: true,
-                enableCommandUris: true,
-                enableFindWidget: true,
-                retainContextWhenHidden: true,
-                localResourceRoots: markdownService.localResourceRoots,
-            });
-            this.panel.onDidDispose(this.onDidDisposeWebview, this, this.listeners);
-            this.panel.webview.onDidReceiveMessage(this.onDidReceiveMessage, this, this.listeners);
-            workspace.onDidChangeConfiguration(this.onDidChangeConfiguration, this, this.listeners);
-        } else {
-            this.panel.title = title;
-            if (viewColumn === ViewColumn.Two) {
-                // Make sure second group exists. See vscode#71608 issue
-                commands.executeCommand("workbench.action.focusSecondEditorGroup").then(() => {
-                    this.panel!.reveal(viewColumn, preserveFocus);
-                });
-            } else {
-                this.panel.reveal(viewColumn, preserveFocus);
-            }
+  protected showWebviewInternal(): void {
+    const { title, viewColumn, preserveFocus } = this.getWebviewOption();
+    if (!this.panel) {
+      this.panel = window.createWebviewPanel(
+        this.viewType,
+        title,
+        { viewColumn, preserveFocus },
+        {
+          enableScripts: true,
+          enableCommandUris: true,
+          enableFindWidget: true,
+          retainContextWhenHidden: true,
+          localResourceRoots: markdownService.localResourceRoots,
         }
-        this.panel.webview.html = this.getWebviewContent();
-        this.showMarkdownConfigHint();
+      );
+      this.panel.onDidDispose(this.onDidDisposeWebview, this, this.listeners);
+      this.panel.webview.onDidReceiveMessage(this.onDidReceiveMessage, this, this.listeners);
+      workspace.onDidChangeConfiguration(this.onDidChangeConfiguration, this, this.listeners);
+    } else {
+      this.panel.title = title;
+      if (viewColumn === ViewColumn.Two) {
+        // Make sure second group exists. See vscode#71608 issue
+        commands.executeCommand("workbench.action.focusSecondEditorGroup").then(() => {
+          this.panel!.reveal(viewColumn, preserveFocus);
+        });
+      } else {
+        this.panel.reveal(viewColumn, preserveFocus);
+      }
     }
+    this.panel.webview.html = this.getWebviewContent();
+    this.showMarkdownConfigHint();
+  }
 
-    protected onDidDisposeWebview(): void {
-        this.panel = undefined;
-        for (const listener of this.listeners) {
-            listener.dispose();
-        }
-        this.listeners = [];
+  protected onDidDisposeWebview(): void {
+    this.panel = undefined;
+    for (const listener of this.listeners) {
+      listener.dispose();
     }
+    this.listeners = [];
+  }
 
-    protected async onDidChangeConfiguration(event: ConfigurationChangeEvent): Promise {
-        if (this.panel && event.affectsConfiguration("markdown")) {
-            this.panel.webview.html = this.getWebviewContent();
-        }
+  protected async onDidChangeConfiguration(event: ConfigurationChangeEvent): Promise {
+    if (this.panel && event.affectsConfiguration("markdown")) {
+      this.panel.webview.html = this.getWebviewContent();
     }
+  }
 
-    protected async onDidReceiveMessage(_message: any): Promise { /* no special rule */ }
+  protected async onDidReceiveMessage(_message: any): Promise {
+    /* no special rule */
+  }
 
-    protected abstract getWebviewOption(): IWebViewOption;
+  protected abstract getWebviewOption(): IWebViewOption;
 
-    protected abstract getWebviewContent(): string;
+  protected abstract getWebviewContent(): string;
 
-    private async showMarkdownConfigHint(): Promise {
-        await promptHintMessage(
-            "hint.configWebviewMarkdown",
-            'You can change the webview appearance ("fontSize", "lineWidth" & "fontFamily") in "markdown.preview" configuration.',
-            "Open settings",
-            (): Promise => openSettingsEditor("markdown.preview"),
-        );
-    }
+  private async showMarkdownConfigHint(): Promise {
+    await promptHintMessage(
+      "hint.configWebviewMarkdown",
+      'You can change the webview appearance ("fontSize", "lineWidth" & "fontFamily") in "markdown.preview" configuration.',
+      "Open settings",
+      (): Promise => openSettingsEditor("markdown.preview")
+    );
+  }
 }
-
diff --git a/src/service/EventService.ts b/src/service/EventService.ts
index a89d488..03f096e 100644
--- a/src/service/EventService.ts
+++ b/src/service/EventService.ts
@@ -7,43 +7,38 @@
  * Copyright (c) 2022 ccagml . All rights reserved.
  */
 
-
-
 import { EventEmitter } from "events";
 
-
 import { UserStatus } from "../model/Model";
 import { ISubmitEvent } from "../model/Model";
 import { statusBarService } from "../service/StatusBarService";
 import { treeDataService } from "../service/TreeDataService";
 
 class EventService extends EventEmitter {
-
-    constructor() {
-        super();
-    }
-
-    /**
-     * 监听事件
-     */
-    public add_event() {
-        this.on("statusChanged", (userStatus: UserStatus, userName?: string) => {
-            statusBarService.update_status(userStatus, userName);
-            statusBarService.update();
-            treeDataService.cleanUserScore();
-            treeDataService.refresh();
-        });
-        this.on("submit", (e: ISubmitEvent) => {
-            treeDataService.checkSubmit(e);
-        });
-
-        this.on("searchUserContest", (tt) => {
-            statusBarService.update_UserContestInfo(tt);
-            statusBarService.update();
-            treeDataService.refresh();
-        });
-    }
+  constructor() {
+    super();
+  }
+
+  /**
+   * 监听事件
+   */
+  public add_event() {
+    this.on("statusChanged", (userStatus: UserStatus, userName?: string) => {
+      statusBarService.update_status(userStatus, userName);
+      statusBarService.update();
+      treeDataService.cleanUserScore();
+      treeDataService.refresh();
+    });
+    this.on("submit", (e: ISubmitEvent) => {
+      treeDataService.checkSubmit(e);
+    });
+
+    this.on("searchUserContest", (tt) => {
+      statusBarService.update_UserContestInfo(tt);
+      statusBarService.update();
+      treeDataService.refresh();
+    });
+  }
 }
 
 export const eventService: EventService = new EventService();
-
diff --git a/src/service/ExecuteService.ts b/src/service/ExecuteService.ts
index d33ef5e..5becaba 100644
--- a/src/service/ExecuteService.ts
+++ b/src/service/ExecuteService.ts
@@ -7,7 +7,6 @@
  * Copyright (c) 2022 ccagml . All rights reserved.
  */
 
-
 import * as cp from "child_process";
 import * as fse from "fs-extra";
 import * as os from "os";
@@ -22,253 +21,331 @@ import * as systemUtils from "../utils/SystemUtils";
 import { toWslPath, useWsl } from "../utils/SystemUtils";
 
 class ExecuteService implements Disposable {
-    private leetCodeCliResourcesRootPath: string;
-    private leetCodeCliRootPath: string;
-    private nodeExecutable: string;
-    private configurationChangeListener: Disposable;
-
-    constructor() {
-        // this.leetCodeCliResourcesRootPath = path.join(__dirname, "..", "..", "node_modules", "childProcessCall");
-        if (!systemUtils.useVscodeNode()) {
-            this.leetCodeCliResourcesRootPath = path.join(__dirname, "..", "..", "..", "resources");
-        }
-        this.leetCodeCliRootPath = path.join(__dirname, "..", "..", "..", "out", "src", "childProcessCall");
+  private leetCodeCliResourcesRootPath: string;
+  private leetCodeCliRootPath: string;
+  private nodeExecutable: string;
+  private configurationChangeListener: Disposable;
+
+  constructor() {
+    // this.leetCodeCliResourcesRootPath = path.join(__dirname, "..", "..", "node_modules", "rpc");
+    if (!systemUtils.useVscodeNode()) {
+      this.leetCodeCliResourcesRootPath = path.join(__dirname, "..", "..", "..", "resources");
+    }
+    this.leetCodeCliRootPath = path.join(__dirname, "..", "..", "..", "out", "src", "rpc");
+    this.nodeExecutable = this.initNodePath();
+    this.configurationChangeListener = workspace.onDidChangeConfiguration((event: ConfigurationChangeEvent) => {
+      if (event.affectsConfiguration("leetcode-problem-rating.nodePath")) {
         this.nodeExecutable = this.initNodePath();
-        this.configurationChangeListener = workspace.onDidChangeConfiguration((event: ConfigurationChangeEvent) => {
-            if (event.affectsConfiguration("leetcode-problem-rating.nodePath")) {
-                this.nodeExecutable = this.initNodePath();
-            }
-        }, this);
+      }
+    }, this);
+  }
+
+  public async getLeetCodeBinaryPath(): Promise {
+    if (systemUtils.useVscodeNode()) {
+      return `${path.join(this.leetCodeCliRootPath, "childMain.js")}`;
+    } else {
+      if (systemUtils.useWsl()) {
+        return `${await systemUtils.toWslPath(`"${path.join(this.leetCodeCliResourcesRootPath, "bin", "leetcode")}"`)}`;
+      }
+      return `"${path.join(this.leetCodeCliResourcesRootPath, "bin", "leetcode")}"`;
     }
+  }
 
-    public async getLeetCodeBinaryPath(): Promise {
-        if (systemUtils.useVscodeNode()) {
-            return `${path.join(this.leetCodeCliRootPath, "cli.js")}`;
-        } else {
-            if (systemUtils.useWsl()) {
-                return `${await systemUtils.toWslPath(`"${path.join(this.leetCodeCliResourcesRootPath, "bin", "leetcode")}"`)}`;
-            }
-            return `"${path.join(this.leetCodeCliResourcesRootPath, "bin", "leetcode")}"`;
-        }
+  public async checkNodeEnv(context: ExtensionContext): Promise {
+    const hasInited: boolean | undefined = context.globalState.get(leetcodeHasInited);
+    if (!hasInited) {
+      await this.removeOldCache();
     }
-
-    public async checkNodeEnv(context: ExtensionContext): Promise {
-        const hasInited: boolean | undefined = context.globalState.get(leetcodeHasInited);
-        if (!hasInited) {
-            await this.removeOldCache();
-        }
-        if (this.nodeExecutable !== "node") {
-            if (!await fse.pathExists(this.nodeExecutable)) {
-                throw new Error(`The Node.js executable does not exist on path ${this.nodeExecutable}`);
-            }
-            // Wrap the executable with "" to avoid space issue in the path.
-            this.nodeExecutable = `"${this.nodeExecutable}"`;
-            if (useWsl()) {
-                this.nodeExecutable = await toWslPath(this.nodeExecutable);
-            }
-        }
-        try {
-            await this.executeCommandEx(this.nodeExecutable, ["-v"]);
-        } catch (error) {
-            const choice: MessageItem | undefined = await window.showErrorMessage(
-                "LeetCode extension needs Node.js installed in environment path",
-                DialogOptions.open,
-            );
-            if (choice === DialogOptions.open) {
-                openUrl("https://nodejs.org");
-            }
-            return false;
-        }
-        context.globalState.update(leetcodeHasInited, true);
-        return true;
+    if (this.nodeExecutable !== "node") {
+      if (!(await fse.pathExists(this.nodeExecutable))) {
+        throw new Error(`The Node.js executable does not exist on path ${this.nodeExecutable}`);
+      }
+      // Wrap the executable with "" to avoid space issue in the path.
+      this.nodeExecutable = `"${this.nodeExecutable}"`;
+      if (useWsl()) {
+        this.nodeExecutable = await toWslPath(this.nodeExecutable);
+      }
     }
-
-    public async deleteCache() {
-        try {
-            await this.executeCommandEx(this.nodeExecutable, [await this.getLeetCodeBinaryPath(), "cache", "-d"]);
-        } catch (error) {
-            await promptForOpenOutputChannel("Failed to delete cache. 请查看控制台信息~", DialogType.error);
-        }
+    try {
+      await this.executeCommandEx(this.nodeExecutable, ["-v"]);
+    } catch (error) {
+      const choice: MessageItem | undefined = await window.showErrorMessage(
+        "LeetCode extension needs Node.js installed in environment path",
+        DialogOptions.open
+      );
+      if (choice === DialogOptions.open) {
+        openUrl("https://nodejs.org");
+      }
+      return false;
     }
-
-    public async getUserInfo(): Promise {
-        return await this.executeCommandEx(this.nodeExecutable, [await this.getLeetCodeBinaryPath(), "user"]);
+    context.globalState.update(leetcodeHasInited, true);
+    return true;
+  }
+
+  public async deleteCache() {
+    try {
+      await this.executeCommandEx(this.nodeExecutable, [await this.getLeetCodeBinaryPath(), "cache", "-d"]);
+    } catch (error) {
+      await promptForOpenOutputChannel("Failed to delete cache. 请查看控制台信息~", DialogType.error);
     }
+  }
 
-    public async signOut(): Promise {
-        return await this.executeCommandEx(this.nodeExecutable, [await this.getLeetCodeBinaryPath(), "user", "-L"]);
-    }
+  public async getUserInfo(): Promise {
+    return await this.executeCommandEx(this.nodeExecutable, [await this.getLeetCodeBinaryPath(), "user"]);
+  }
 
-    public async listProblems(showLocked: boolean, needTranslation: boolean): Promise {
-        const cmd: string[] = [await this.getLeetCodeBinaryPath(), "list"];
-        if (!needTranslation) {
-            cmd.push("-T"); // use -T to prevent translation
-        }
-        if (!showLocked) {
-            cmd.push("-q");
-            cmd.push("L");
-        }
-        return await this.executeCommandEx(this.nodeExecutable, cmd);
-    }
+  public async signOut(): Promise {
+    return await this.executeCommandEx(this.nodeExecutable, [await this.getLeetCodeBinaryPath(), "user", "-L"]);
+  }
 
-    public async showProblem(problemNode: IProblem, language: string, filePath: string, showDescriptionInComment: boolean = false, needTranslation: boolean): Promise {
-        const templateType: string = showDescriptionInComment ? "-cx" : "-c";
-        const cmd: string[] = [await this.getLeetCodeBinaryPath(), "show", problemNode.qid, templateType, "-l", language];
-
-        if (!needTranslation) {
-            cmd.push("-T"); // use -T to force English version
-        }
-
-        if (!await fse.pathExists(filePath)) {
-            await fse.createFile(filePath);
-            const codeTemplate: string = await this.executeCommandWithProgressEx("Fetching problem data...", this.nodeExecutable, cmd);
-            await fse.writeFile(filePath, codeTemplate);
-        }
+  public async listProblems(showLocked: boolean, needTranslation: boolean): Promise {
+    const cmd: string[] = [await this.getLeetCodeBinaryPath(), "list"];
+    if (!needTranslation) {
+      cmd.push("-T"); // use -T to prevent translation
     }
-
-
-    public async showSolution(input: string, language: string, needTranslation: boolean): Promise {
-        // solution don't support translation
-        const cmd: string[] = [await this.getLeetCodeBinaryPath(), "show", input, "--solution", "-l", language];
-        if (!needTranslation) {
-            cmd.push("-T");
-        }
-        const solution: string = await this.executeCommandWithProgressEx("Fetching top voted solution from discussions...", this.nodeExecutable, cmd);
-        return solution;
+    if (!showLocked) {
+      cmd.push("-q");
+      cmd.push("L");
     }
-
-    public async getUserContest(needTranslation: boolean, username: string): Promise {
-        // solution don't support translation
-        const cmd: string[] = [await this.getLeetCodeBinaryPath(), "query", "-b", username];
-        if (!needTranslation) {
-            cmd.push("-T");
-        }
-        const solution: string = await this.executeCommandWithProgressEx("Fetching UserContest...", this.nodeExecutable, cmd);
-        return solution;
+    return await this.executeCommandEx(this.nodeExecutable, cmd);
+  }
+
+  public async showProblem(
+    problemNode: IProblem,
+    language: string,
+    filePath: string,
+    showDescriptionInComment: boolean = false,
+    needTranslation: boolean
+  ): Promise {
+    const templateType: string = showDescriptionInComment ? "-cx" : "-c";
+    const cmd: string[] = [await this.getLeetCodeBinaryPath(), "show", problemNode.qid, templateType, "-l", language];
+
+    if (!needTranslation) {
+      cmd.push("-T"); // use -T to force English version
     }
 
-    public async getScoreDataOnline(): Promise {
-        // solution don't support translation
-        const cmd: string[] = [await this.getLeetCodeBinaryPath(), "query", "-c"];
-        const solution: string = await this.executeCommandWithProgressEx("get data from https://zerotrac.github.io/leetcode_problem_rating/data.json", this.nodeExecutable, cmd);
-        return solution;
+    if (!(await fse.pathExists(filePath))) {
+      await fse.createFile(filePath);
+      const codeTemplate: string = await this.executeCommandWithProgressEx(
+        "Fetching problem data...",
+        this.nodeExecutable,
+        cmd
+      );
+      await fse.writeFile(filePath, codeTemplate);
     }
+  }
 
-    public async getTestApi(username: string): Promise {
-        // solution don't support translation
-        const cmd: string[] = [await this.getLeetCodeBinaryPath(), "query", "-z", username];
-        const solution: string = await this.executeCommandWithProgressEx("Fetching testapi...", this.nodeExecutable, cmd);
-        return solution;
+  public async showSolution(input: string, language: string, needTranslation: boolean): Promise {
+    // solution don't support translation
+    const cmd: string[] = [await this.getLeetCodeBinaryPath(), "show", input, "--solution", "-l", language];
+    if (!needTranslation) {
+      cmd.push("-T");
     }
-
-    public async getTodayQuestion(needTranslation: boolean): Promise {
-        // solution don't support translation
-        const cmd: string[] = [await this.getLeetCodeBinaryPath(), "query", "-a"];
-        if (!needTranslation) {
-            cmd.push("-T");
-        }
-        const solution: string = await this.executeCommandWithProgressEx("Fetching today question...", this.nodeExecutable, cmd);
-        return solution;
+    const solution: string = await this.executeCommandWithProgressEx(
+      "Fetching top voted solution from discussions...",
+      this.nodeExecutable,
+      cmd
+    );
+    return solution;
+  }
+
+  public async getUserContest(needTranslation: boolean, username: string): Promise {
+    // solution don't support translation
+    const cmd: string[] = [await this.getLeetCodeBinaryPath(), "query", "-b", username];
+    if (!needTranslation) {
+      cmd.push("-T");
     }
-
-
-    public async getDescription(problemNodeId: string, needTranslation: boolean): Promise {
-        const cmd: string[] = [await this.getLeetCodeBinaryPath(), "show", problemNodeId, "-x"];
-        if (!needTranslation) {
-            cmd.push("-T");
-        }
-        return await this.executeCommandWithProgressEx("Fetching problem description...", this.nodeExecutable, cmd);
+    const solution: string = await this.executeCommandWithProgressEx(
+      "Fetching UserContest...",
+      this.nodeExecutable,
+      cmd
+    );
+    return solution;
+  }
+
+  public async getScoreDataOnline(): Promise {
+    // solution don't support translation
+    const cmd: string[] = [await this.getLeetCodeBinaryPath(), "query", "-c"];
+    const solution: string = await this.executeCommandWithProgressEx(
+      "get data from https://zerotrac.github.io/leetcode_problem_rating/data.json",
+      this.nodeExecutable,
+      cmd
+    );
+    return solution;
+  }
+
+  public async getTestApi(username: string): Promise {
+    // solution don't support translation
+    const cmd: string[] = [await this.getLeetCodeBinaryPath(), "query", "-z", username];
+    const solution: string = await this.executeCommandWithProgressEx("Fetching testapi...", this.nodeExecutable, cmd);
+    return solution;
+  }
+
+  public async getTodayQuestion(needTranslation: boolean): Promise {
+    // solution don't support translation
+    const cmd: string[] = [await this.getLeetCodeBinaryPath(), "query", "-a"];
+    if (!needTranslation) {
+      cmd.push("-T");
     }
-
-
-    public async submitSolution(filePath: string): Promise {
-        try {
-            if (systemUtils.useVscodeNode()) {
-                return await this.executeCommandWithProgressEx("Submitting to LeetCode...", this.nodeExecutable, [await this.getLeetCodeBinaryPath(), "submit", `${filePath}`]);
-            }
-            return await this.executeCommandWithProgressEx("Submitting to LeetCode...", this.nodeExecutable, [await this.getLeetCodeBinaryPath(), "submit", `"${filePath}"`]);
-        } catch (error) {
-            if (error.result) {
-                return error.result;
-            }
-            throw error;
-        }
+    const solution: string = await this.executeCommandWithProgressEx(
+      "Fetching today question...",
+      this.nodeExecutable,
+      cmd
+    );
+    return solution;
+  }
+
+  public async getDescription(problemNodeId: string, needTranslation: boolean): Promise {
+    const cmd: string[] = [await this.getLeetCodeBinaryPath(), "show", problemNodeId, "-x"];
+    if (!needTranslation) {
+      cmd.push("-T");
     }
-
-    public async testSolution(filePath: string, testString?: string, allCase?: boolean): Promise {
-        if (testString) {
-            if (systemUtils.useVscodeNode()) {
-                return await this.executeCommandWithProgressEx("Submitting to LeetCode...", this.nodeExecutable, [await this.getLeetCodeBinaryPath(), "test", `${filePath}`, "-t", `${testString}`]);
-            }
-            return await this.executeCommandWithProgressEx("Submitting to LeetCode...", this.nodeExecutable, [await this.getLeetCodeBinaryPath(), "test", `"${filePath}"`, "-t", `${testString}`]);
-        }
-        if (allCase) {
-            if (systemUtils.useVscodeNode()) {
-                return await this.executeCommandWithProgressEx("Submitting to LeetCode...", this.nodeExecutable, [await this.getLeetCodeBinaryPath(), "test", `${filePath}`, "-a"]);
-            }
-            return await this.executeCommandWithProgressEx("Submitting to LeetCode...", this.nodeExecutable, [await this.getLeetCodeBinaryPath(), "test", `"${filePath}"`, "-a"]);
-        }
-        if (systemUtils.useVscodeNode()) {
-            return await this.executeCommandWithProgressEx("Submitting to LeetCode...", this.nodeExecutable, [await this.getLeetCodeBinaryPath(), "test", `${filePath}`]);
-        }
-        return await this.executeCommandWithProgressEx("Submitting to LeetCode...", this.nodeExecutable, [await this.getLeetCodeBinaryPath(), "test", `"${filePath}"`]);
+    return await this.executeCommandWithProgressEx("Fetching problem description...", this.nodeExecutable, cmd);
+  }
+
+  public async submitSolution(filePath: string): Promise {
+    try {
+      if (systemUtils.useVscodeNode()) {
+        return await this.executeCommandWithProgressEx("Submitting to LeetCode...", this.nodeExecutable, [
+          await this.getLeetCodeBinaryPath(),
+          "submit",
+          `${filePath}`,
+        ]);
+      }
+      return await this.executeCommandWithProgressEx("Submitting to LeetCode...", this.nodeExecutable, [
+        await this.getLeetCodeBinaryPath(),
+        "submit",
+        `"${filePath}"`,
+      ]);
+    } catch (error) {
+      if (error.result) {
+        return error.result;
+      }
+      throw error;
     }
-
-    public async switchEndpoint(endpoint: string): Promise {
-        switch (endpoint) {
-            case Endpoint.LeetCodeCN:
-                return await this.executeCommandEx(this.nodeExecutable, [await this.getLeetCodeBinaryPath(), "plugin", "-e", "leetcode.cn"]);
-            case Endpoint.LeetCode:
-            default:
-                return await this.executeCommandEx(this.nodeExecutable, [await this.getLeetCodeBinaryPath(), "plugin", "-d", "leetcode.cn"]);
-        }
+  }
+
+  public async testSolution(filePath: string, testString?: string, allCase?: boolean): Promise {
+    if (testString) {
+      if (systemUtils.useVscodeNode()) {
+        return await this.executeCommandWithProgressEx("Submitting to LeetCode...", this.nodeExecutable, [
+          await this.getLeetCodeBinaryPath(),
+          "test",
+          `${filePath}`,
+          "-t",
+          `${testString}`,
+        ]);
+      }
+      return await this.executeCommandWithProgressEx("Submitting to LeetCode...", this.nodeExecutable, [
+        await this.getLeetCodeBinaryPath(),
+        "test",
+        `"${filePath}"`,
+        "-t",
+        `${testString}`,
+      ]);
     }
-
-    public async toggleFavorite(node: IProblem, addToFavorite: boolean): Promise {
-        const commandParams: string[] = [await this.getLeetCodeBinaryPath(), "star", node.id];
-        if (!addToFavorite) {
-            commandParams.push("-d");
-        }
-        await this.executeCommandWithProgressEx("Updating the favorite list...", "node", commandParams);
+    if (allCase) {
+      if (systemUtils.useVscodeNode()) {
+        return await this.executeCommandWithProgressEx("Submitting to LeetCode...", this.nodeExecutable, [
+          await this.getLeetCodeBinaryPath(),
+          "test",
+          `${filePath}`,
+          "-a",
+        ]);
+      }
+      return await this.executeCommandWithProgressEx("Submitting to LeetCode...", this.nodeExecutable, [
+        await this.getLeetCodeBinaryPath(),
+        "test",
+        `"${filePath}"`,
+        "-a",
+      ]);
     }
-
-
-    public get node(): string {
-        return this.nodeExecutable;
+    if (systemUtils.useVscodeNode()) {
+      return await this.executeCommandWithProgressEx("Submitting to LeetCode...", this.nodeExecutable, [
+        await this.getLeetCodeBinaryPath(),
+        "test",
+        `${filePath}`,
+      ]);
     }
-
-    public dispose(): void {
-        this.configurationChangeListener.dispose();
+    return await this.executeCommandWithProgressEx("Submitting to LeetCode...", this.nodeExecutable, [
+      await this.getLeetCodeBinaryPath(),
+      "test",
+      `"${filePath}"`,
+    ]);
+  }
+
+  public async switchEndpoint(endpoint: string): Promise {
+    switch (endpoint) {
+      case Endpoint.LeetCodeCN:
+        return await this.executeCommandEx(this.nodeExecutable, [
+          await this.getLeetCodeBinaryPath(),
+          "plugin",
+          "-e",
+          "leetcode.cn",
+        ]);
+      case Endpoint.LeetCode:
+      default:
+        return await this.executeCommandEx(this.nodeExecutable, [
+          await this.getLeetCodeBinaryPath(),
+          "plugin",
+          "-d",
+          "leetcode.cn",
+        ]);
     }
+  }
 
-    private initNodePath(): string {
-        if (systemUtils.useVscodeNode()) {
-            return "node";
-        }
-        return getNodePath();
+  public async toggleFavorite(node: IProblem, addToFavorite: boolean): Promise {
+    const commandParams: string[] = [await this.getLeetCodeBinaryPath(), "star", node.id];
+    if (!addToFavorite) {
+      commandParams.push("-d");
     }
+    await this.executeCommandWithProgressEx("Updating the favorite list...", "node", commandParams);
+  }
 
-    private async executeCommandEx(command: string, args: string[], options: cp.SpawnOptions = { shell: true }): Promise {
-        if (systemUtils.useWsl()) {
-            return await executeCommand("wsl", [command].concat(args), options);
-        }
-        return await executeCommand(command, args, options);
-    }
+  public get node(): string {
+    return this.nodeExecutable;
+  }
 
-    private async executeCommandWithProgressEx(message: string, command: string, args: string[], options: cp.SpawnOptions = { shell: true }): Promise {
-        if (systemUtils.useWsl()) {
-            return await executeCommandWithProgress(message, "wsl", [command].concat(args), options);
-        }
-        return await executeCommandWithProgress(message, command, args, options);
-    }
+  public dispose(): void {
+    this.configurationChangeListener.dispose();
+  }
 
-    public async removeOldCache(): Promise {
-        const oldPath: string = path.join(os.homedir(), ".lcpr");
-        if (await fse.pathExists(oldPath)) {
-            await fse.remove(oldPath);
-        }
+  private initNodePath(): string {
+    if (systemUtils.useVscodeNode()) {
+      return "node";
     }
+    return getNodePath();
+  }
+
+  private async executeCommandEx(
+    command: string,
+    args: string[],
+    options: cp.SpawnOptions = { shell: true }
+  ): Promise {
+    if (systemUtils.useWsl()) {
+      return await executeCommand("wsl", [command].concat(args), options);
+    }
+    return await executeCommand(command, args, options);
+  }
+
+  private async executeCommandWithProgressEx(
+    message: string,
+    command: string,
+    args: string[],
+    options: cp.SpawnOptions = { shell: true }
+  ): Promise {
+    if (systemUtils.useWsl()) {
+      return await executeCommandWithProgress(message, "wsl", [command].concat(args), options);
+    }
+    return await executeCommandWithProgress(message, command, args, options);
+  }
 
+  public async removeOldCache(): Promise {
+    const oldPath: string = path.join(os.homedir(), ".lcpr");
+    if (await fse.pathExists(oldPath)) {
+      await fse.remove(oldPath);
+    }
+  }
 }
 
 export const executeService: ExecuteService = new ExecuteService();
diff --git a/src/service/FileButtonService.ts b/src/service/FileButtonService.ts
index d922fae..875d308 100644
--- a/src/service/FileButtonService.ts
+++ b/src/service/FileButtonService.ts
@@ -13,103 +13,168 @@ import { NodeModel } from "../model/NodeModel";
 import { getEditorShortcuts } from "../utils/ConfigUtils";
 
 export class FileButtonService implements vscode.CodeLensProvider {
+  private onDidChangeCodeLensesEmitter: vscode.EventEmitter = new vscode.EventEmitter();
+
+  get onDidChangeCodeLenses(): vscode.Event {
+    return this.onDidChangeCodeLensesEmitter.event;
+  }
+
+  public refresh(): void {
+    this.onDidChangeCodeLensesEmitter.fire();
+  }
+
+  // 处理代码的按钮
+  private processCodeButton(codeLensLine, document, node): vscode.CodeLens[] {
+    const temp_result: vscode.CodeLens[] = [];
+    const shortcuts: string[] = getEditorShortcuts();
+    if (!shortcuts) {
+      return temp_result;
+    }
+
+    const range: vscode.Range = new vscode.Range(codeLensLine, 0, codeLensLine, 0);
 
-    private onDidChangeCodeLensesEmitter: vscode.EventEmitter = new vscode.EventEmitter();
+    if (shortcuts.indexOf("submit") >= 0) {
+      temp_result.push(
+        new vscode.CodeLens(range, {
+          title: "Submit",
+          command: "leetcode.submitSolution",
+          arguments: [document.uri],
+        })
+      );
+    }
 
-    get onDidChangeCodeLenses(): vscode.Event {
-        return this.onDidChangeCodeLensesEmitter.event;
+    if (shortcuts.indexOf("case") >= 0) {
+      temp_result.push(
+        new vscode.CodeLens(range, {
+          title: "case",
+          command: "leetcode.testSolutionDefault",
+          arguments: [document.uri, false],
+        })
+      );
+    }
+    if (shortcuts.indexOf("allcase") >= 0) {
+      temp_result.push(
+        new vscode.CodeLens(range, {
+          title: "allcase",
+          command: "leetcode.testSolutionDefault",
+          arguments: [document.uri, true],
+        })
+      );
     }
 
-    public refresh(): void {
-        this.onDidChangeCodeLensesEmitter.fire();
+    if (shortcuts.indexOf("test") >= 0) {
+      temp_result.push(
+        new vscode.CodeLens(range, {
+          title: "Test",
+          command: "leetcode.testSolution",
+          arguments: [document.uri],
+        })
+      );
     }
 
-    public provideCodeLenses(document: vscode.TextDocument): vscode.ProviderResult {
-        const shortcuts: string[] = getEditorShortcuts();
-        if (!shortcuts) {
-            return;
-        }
-
-        const content: string = document.getText();
-        const matchResult: RegExpMatchArray | null = content.match(/@lc app=.* id=(.*) lang=.*/);
-        if (!matchResult) {
-            return undefined;
-        }
-        const nodeId: string | undefined = matchResult[1];
-        let node: NodeModel | undefined;
-        if (nodeId) {
-            node = treeViewController.getNodeById(nodeId);
-        }
-
-        let codeLensLine: number = document.lineCount - 1;
-        for (let i: number = document.lineCount - 1; i >= 0; i--) {
-            const lineContent: string = document.lineAt(i).text;
-            if (lineContent.indexOf("@lc code=end") >= 0) {
-                codeLensLine = i;
-                break;
-            }
-        }
-
-        const range: vscode.Range = new vscode.Range(codeLensLine, 0, codeLensLine, 0);
-        const codeLens: vscode.CodeLens[] = [];
-
-        if (shortcuts.indexOf("submit") >= 0) {
-            codeLens.push(new vscode.CodeLens(range, {
-                title: "Submit",
-                command: "leetcode.submitSolution",
-                arguments: [document.uri],
-            }));
-        }
-
-        if (shortcuts.indexOf("case") >= 0) {
-            codeLens.push(new vscode.CodeLens(range, {
-                title: "case",
-                command: "leetcode.testSolutionDefault",
-                arguments: [document.uri, false],
-            }));
-        }
-        if (shortcuts.indexOf("allcase") >= 0) {
-            codeLens.push(new vscode.CodeLens(range, {
-                title: "allcase",
-                command: "leetcode.testSolutionDefault",
-                arguments: [document.uri, true],
-            }));
-        }
-
-        if (shortcuts.indexOf("test") >= 0) {
-            codeLens.push(new vscode.CodeLens(range, {
-                title: "Test",
-                command: "leetcode.testSolution",
-                arguments: [document.uri],
-            }));
-        }
-
-        if (shortcuts.indexOf("star") >= 0 && node) {
-            codeLens.push(new vscode.CodeLens(range, {
-                title: node.isFavorite ? "Unstar" : "Star",
-                command: node.isFavorite ? "leetcode.removeFavorite" : "leetcode.addFavorite",
-                arguments: [node],
-            }));
-        }
-
-        if (shortcuts.indexOf("solution") >= 0) {
-            codeLens.push(new vscode.CodeLens(range, {
-                title: "Solution",
-                command: "leetcode.showSolution",
-                arguments: [document.uri],
-            }));
-        }
-
-        if (shortcuts.indexOf("description") >= 0) {
-            codeLens.push(new vscode.CodeLens(range, {
-                title: "Description",
-                command: "leetcode.previewProblem",
-                arguments: [document.uri],
-            }));
-        }
-
-        return codeLens;
+    if (shortcuts.indexOf("star") >= 0 && node) {
+      temp_result.push(
+        new vscode.CodeLens(range, {
+          title: node.isFavorite ? "Unstar" : "Star",
+          command: node.isFavorite ? "leetcode.removeFavorite" : "leetcode.addFavorite",
+          arguments: [node],
+        })
+      );
     }
+
+    if (shortcuts.indexOf("solution") >= 0) {
+      temp_result.push(
+        new vscode.CodeLens(range, {
+          title: "Solution",
+          command: "leetcode.showSolution",
+          arguments: [document.uri],
+        })
+      );
+    }
+
+    if (shortcuts.indexOf("description") >= 0) {
+      temp_result.push(
+        new vscode.CodeLens(range, {
+          title: "Description",
+          command: "leetcode.previewProblem",
+          arguments: [document.uri],
+        })
+      );
+    }
+    return temp_result;
+  }
+
+  /**
+   * createCase
+   */
+  public createCase(codeLensLine, document, testCase) {
+    const range: vscode.Range = new vscode.Range(codeLensLine, 0, codeLensLine, 0);
+
+    return new vscode.CodeLens(range, {
+      title: "case",
+      command: "leetcode.testSolutionArea",
+      arguments: [document.uri, testCase],
+    });
+  }
+
+  public singleLineFlag = {
+    bash: "#",
+    c: "//",
+    cpp: "//",
+    csharp: "//",
+    golang: "//",
+    java: "//",
+    javascript: "//",
+    kotlin: "//",
+    mysql: "--",
+    php: "//",
+    python: "#",
+    python3: "#",
+    ruby: "#",
+    rust: "//",
+    scala: "//",
+    swift: "//",
+    typescript: "//",
+  };
+
+  public provideCodeLenses(document: vscode.TextDocument): vscode.ProviderResult {
+    const content: string = document.getText();
+    const matchResult: RegExpMatchArray | null = content.match(/@lc app=.* id=(.*) lang=.*/);
+    if (!matchResult) {
+      return undefined;
+    }
+    const nodeId: string | undefined = matchResult[1];
+    let node: NodeModel | undefined;
+    if (nodeId) {
+      node = treeViewController.getNodeById(nodeId);
+    }
+
+    const codeLens: vscode.CodeLens[] = [];
+    let caseFlag: boolean = false;
+    let curCase = "";
+    for (let i: number = 0; i < document.lineCount; i++) {
+      const lineContent: string = document.lineAt(i).text;
+      if (lineContent.indexOf("@lc code=end") >= 0) {
+        this.processCodeButton(i, document, node).forEach((x) => codeLens.push(x));
+      }
+
+      if (caseFlag && lineContent.indexOf("@lcpr case=end") < 0) {
+        curCase += lineContent.replace(/#/g, "").replace(/\/\//g, "").replace(/--/g, "").replace(/\s+/g, "");
+      }
+      // 收集所有用例
+      if (lineContent.indexOf("@lcpr case=start") >= 0) {
+        caseFlag = true;
+      }
+
+      if (caseFlag && lineContent.indexOf("@lcpr case=end") >= 0) {
+        codeLens.push(this.createCase(i, document, curCase));
+        curCase = "";
+        caseFlag = false;
+      }
+    }
+
+    return codeLens;
+  }
 }
 
 export const fileButtonService: FileButtonService = new FileButtonService();
diff --git a/src/service/MarkdownService.ts b/src/service/MarkdownService.ts
index a2e8405..13c75df 100644
--- a/src/service/MarkdownService.ts
+++ b/src/service/MarkdownService.ts
@@ -7,7 +7,6 @@
  * Copyright (c) 2022 ccagml . All rights reserved.
  */
 
-
 import * as hljs from "highlight.js";
 import * as MarkdownIt from "markdown-it";
 import * as os from "os";
@@ -17,157 +16,165 @@ import { logOutput } from "../utils/OutputUtils";
 import { isWindows } from "../utils/SystemUtils";
 
 class MarkdownService implements vscode.Disposable {
-
-    private engine: MarkdownIt;
-    private config: MarkdownConfiguration;
-    private listener: vscode.Disposable;
-
-    public constructor() {
+  private engine: MarkdownIt;
+  private config: MarkdownConfiguration;
+  private listener: vscode.Disposable;
+
+  public constructor() {
+    this.reload();
+    this.listener = vscode.workspace.onDidChangeConfiguration((event: vscode.ConfigurationChangeEvent) => {
+      if (event.affectsConfiguration("markdown")) {
         this.reload();
-        this.listener = vscode.workspace.onDidChangeConfiguration((event: vscode.ConfigurationChangeEvent) => {
-            if (event.affectsConfiguration("markdown")) {
-                this.reload();
-            }
-        }, this);
-    }
-
-    public get localResourceRoots(): vscode.Uri[] {
-        return [vscode.Uri.file(path.join(this.config.extRoot, "media"))];
-    }
-
-    public dispose(): void {
-        this.listener.dispose();
+      }
+    }, this);
+  }
+
+  public get localResourceRoots(): vscode.Uri[] {
+    return [vscode.Uri.file(path.join(this.config.extRoot, "media"))];
+  }
+
+  public dispose(): void {
+    this.listener.dispose();
+  }
+
+  public reload(): void {
+    this.engine = this.initEngine();
+    this.config = new MarkdownConfiguration();
+  }
+
+  public render(md: string, env?: any): string {
+    return this.engine.render(md, env);
+  }
+
+  public getStyles(): string {
+    return [this.getBuiltinStyles(), this.getSettingsStyles()].join(os.EOL);
+  }
+
+  private getBuiltinStyles(): string {
+    let styles: vscode.Uri[] = [];
+    try {
+      const stylePaths: string[] = require(path.join(this.config.extRoot, "package.json"))["contributes"][
+        "markdown.previewStyles"
+      ];
+      styles = stylePaths.map((p: string) =>
+        vscode.Uri.file(path.join(this.config.extRoot, p)).with({
+          scheme: "vscode-resource",
+        })
+      );
+    } catch (error) {
+      logOutput.appendLine("[Error] Fail to load built-in markdown style file.");
     }
-
-    public reload(): void {
-        this.engine = this.initEngine();
-        this.config = new MarkdownConfiguration();
-    }
-
-    public render(md: string, env?: any): string {
-        return this.engine.render(md, env);
-    }
-
-    public getStyles(): string {
-        return [
-            this.getBuiltinStyles(),
-            this.getSettingsStyles(),
-        ].join(os.EOL);
-    }
-
-    private getBuiltinStyles(): string {
-        let styles: vscode.Uri[] = [];
-        try {
-            const stylePaths: string[] = require(path.join(this.config.extRoot, "package.json"))["contributes"]["markdown.previewStyles"];
-            styles = stylePaths.map((p: string) => vscode.Uri.file(path.join(this.config.extRoot, p)).with({ scheme: "vscode-resource" }));
-        } catch (error) {
-            logOutput.appendLine("[Error] Fail to load built-in markdown style file.");
+    return styles
+      .map((style: vscode.Uri) => ``)
+      .join(os.EOL);
+  }
+
+  private getSettingsStyles(): string {
+    return [
+      ``,
+    ].join(os.EOL);
+  }
+
+  private initEngine(): MarkdownIt {
+    const md: MarkdownIt = new MarkdownIt({
+      linkify: true,
+      typographer: true,
+      highlight: (code: string, lang?: string): string => {
+        switch (lang && lang.toLowerCase()) {
+          case "mysql":
+            lang = "sql";
+            break;
+          case "json5":
+            lang = "json";
+            break;
+          case "python3":
+            lang = "python";
+            break;
         }
-        return styles.map((style: vscode.Uri) => ``).join(os.EOL);
-    }
-
-    private getSettingsStyles(): string {
-        return [
-            ``,
-        ].join(os.EOL);
-    }
-
-    private initEngine(): MarkdownIt {
-        const md: MarkdownIt = new MarkdownIt({
-            linkify: true,
-            typographer: true,
-            highlight: (code: string, lang?: string): string => {
-                switch (lang && lang.toLowerCase()) {
-                    case "mysql":
-                        lang = "sql"; break;
-                    case "json5":
-                        lang = "json"; break;
-                    case "python3":
-                        lang = "python"; break;
-                }
-                if (lang && hljs.getLanguage(lang)) {
-                    try {
-                        return hljs.highlight(lang, code, true).value;
-                    } catch (error) { /* do not highlight */ }
-                }
-                return ""; // use external default escaping
-            },
-        });
-
-        this.addCodeBlockHighlight(md);
-        this.addImageUrlCompletion(md);
-        this.addLinkValidator(md);
-        return md;
-    }
-
-    private addCodeBlockHighlight(md: MarkdownIt): void {
-        const codeBlock: MarkdownIt.TokenRender = md.renderer.rules["code_block"];
-        // tslint:disable-next-line:typedef
-        md.renderer.rules["code_block"] = (tokens, idx, options, env, self) => {
-            // if any token uses lang-specified code fence, then do not highlight code block
-            if (tokens.some((token: any) => token.type === "fence")) {
-                return codeBlock(tokens, idx, options, env, self);
-            }
-            // otherwise, highlight with default lang in env object.
-            const highlighted: string = options.highlight(tokens[idx].content, env.lang);
-            return [
-                `
`,
-                highlighted || md.utils.escapeHtml(tokens[idx].content),
-                "
", - ].join(os.EOL); - }; - } - - private addImageUrlCompletion(md: MarkdownIt): void { - const image: MarkdownIt.TokenRender = md.renderer.rules["image"]; - // tslint:disable-next-line:typedef - md.renderer.rules["image"] = (tokens, idx, options, env, self) => { - const imageSrc: string[] | undefined = tokens[idx].attrs.find((value: string[]) => value[0] === "src"); - if (env.host && imageSrc && imageSrc[1].startsWith("/")) { - imageSrc[1] = `${env.host}${imageSrc[1]}`; - } - return image(tokens, idx, options, env, self); - }; - } - - private addLinkValidator(md: MarkdownIt): void { - const validateLink: (link: string) => boolean = md.validateLink; - md.validateLink = (link: string): boolean => { - // support file:// protocal link - return validateLink(link) || link.startsWith("file:"); - }; - } + if (lang && hljs.getLanguage(lang)) { + try { + return hljs.highlight(lang, code, true).value; + } catch (error) { + /* do not highlight */ + } + } + return ""; // use external default escaping + }, + }); + + this.addCodeBlockHighlight(md); + this.addImageUrlCompletion(md); + this.addLinkValidator(md); + return md; + } + + private addCodeBlockHighlight(md: MarkdownIt): void { + const codeBlock: MarkdownIt.TokenRender = md.renderer.rules["code_block"]; + // tslint:disable-next-line:typedef + md.renderer.rules["code_block"] = (tokens, idx, options, env, self) => { + // if any token uses lang-specified code fence, then do not highlight code block + if (tokens.some((token: any) => token.type === "fence")) { + return codeBlock(tokens, idx, options, env, self); + } + // otherwise, highlight with default lang in env object. + const highlighted: string = options.highlight(tokens[idx].content, env.lang); + return [ + `
`,
+        highlighted || md.utils.escapeHtml(tokens[idx].content),
+        "
", + ].join(os.EOL); + }; + } + + private addImageUrlCompletion(md: MarkdownIt): void { + const image: MarkdownIt.TokenRender = md.renderer.rules["image"]; + // tslint:disable-next-line:typedef + md.renderer.rules["image"] = (tokens, idx, options, env, self) => { + const imageSrc: string[] | undefined = tokens[idx].attrs.find((value: string[]) => value[0] === "src"); + if (env.host && imageSrc && imageSrc[1].startsWith("/")) { + imageSrc[1] = `${env.host}${imageSrc[1]}`; + } + return image(tokens, idx, options, env, self); + }; + } + + private addLinkValidator(md: MarkdownIt): void { + const validateLink: (link: string) => boolean = md.validateLink; + md.validateLink = (link: string): boolean => { + // support file:// protocal link + return validateLink(link) || link.startsWith("file:"); + }; + } } // tslint:disable-next-line: max-classes-per-file class MarkdownConfiguration { - - public readonly extRoot: string; // root path of vscode built-in markdown extension - public readonly lineHeight: number; - public readonly fontSize: number; - public readonly fontFamily: string; - - public constructor() { - const markdownConfig: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("markdown", null); - this.extRoot = path.join(vscode.env.appRoot, "extensions", "markdown-language-features"); - this.lineHeight = Math.max(0.6, +markdownConfig.get("preview.lineHeight", NaN)); - this.fontSize = Math.max(8, +markdownConfig.get("preview.fontSize", NaN)); - this.fontFamily = this.resolveFontFamily(markdownConfig); - } - - private resolveFontFamily(config: vscode.WorkspaceConfiguration): string { - let fontFamily: string = config.get("preview.fontFamily", ""); - if (isWindows() && fontFamily === config.inspect("preview.fontFamily")!.defaultValue) { - fontFamily = `${fontFamily}, 'Microsoft Yahei UI'`; - } - return fontFamily; + public readonly extRoot: string; // root path of vscode built-in markdown extension + public readonly lineHeight: number; + public readonly fontSize: number; + public readonly fontFamily: string; + + public constructor() { + const markdownConfig: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("markdown", null); + this.extRoot = path.join(vscode.env.appRoot, "extensions", "markdown-language-features"); + this.lineHeight = Math.max(0.6, +markdownConfig.get("preview.lineHeight", NaN)); + this.fontSize = Math.max(8, +markdownConfig.get("preview.fontSize", NaN)); + this.fontFamily = this.resolveFontFamily(markdownConfig); + } + + private resolveFontFamily(config: vscode.WorkspaceConfiguration): string { + let fontFamily: string = config.get("preview.fontFamily", ""); + if (isWindows() && fontFamily === config.inspect("preview.fontFamily")!.defaultValue) { + fontFamily = `${fontFamily}, 'Microsoft Yahei UI'`; } + return fontFamily; + } } export const markdownService: MarkdownService = new MarkdownService(); diff --git a/src/service/PreviewService.ts b/src/service/PreviewService.ts index ff94145..dd872bd 100644 --- a/src/service/PreviewService.ts +++ b/src/service/PreviewService.ts @@ -7,7 +7,6 @@ * Copyright (c) 2022 ccagml . All rights reserved. */ - import { commands, ViewColumn } from "vscode"; import { Endpoint, IProblem, IWebViewOption } from "../model/Model"; import { getLeetCodeEndpoint } from "../utils/ConfigUtils"; @@ -15,51 +14,50 @@ import { BaseWebViewService } from "./BaseWebviewService"; import { markdownService } from "./MarkdownService"; class PreviewService extends BaseWebViewService { - - protected readonly viewType: string = "leetcode.preview"; - private node: IProblem; - private description: IDescription; - private sideMode: boolean = false; - - public isSideMode(): boolean { - return this.sideMode; - } - - public show(descString: string, node: IProblem, isSideMode: boolean = false): void { - this.description = this.parseDescription(descString, node); - this.node = node; - this.sideMode = isSideMode; - this.showWebviewInternal(); - // Comment out this operation since it sometimes may cause the webview become empty. - // Waiting for the progress of the VS Code side issue: https://github.com/microsoft/vscode/issues/3742 - // if (this.sideMode) { - // this.hideSideBar(); // For better view area - // } - } - - protected getWebviewOption(): IWebViewOption { - if (!this.sideMode) { - return { - title: `${this.node.name}: Preview`, - viewColumn: ViewColumn.One, - }; - } else { - return { - title: "Description", - viewColumn: ViewColumn.Two, - preserveFocus: true, - }; - } + protected readonly viewType: string = "leetcode.preview"; + private node: IProblem; + private description: IDescription; + private sideMode: boolean = false; + + public isSideMode(): boolean { + return this.sideMode; + } + + public show(descString: string, node: IProblem, isSideMode: boolean = false): void { + this.description = this.parseDescription(descString, node); + this.node = node; + this.sideMode = isSideMode; + this.showWebviewInternal(); + // Comment out this operation since it sometimes may cause the webview become empty. + // Waiting for the progress of the VS Code side issue: https://github.com/microsoft/vscode/issues/3742 + // if (this.sideMode) { + // this.hideSideBar(); // For better view area + // } + } + + protected getWebviewOption(): IWebViewOption { + if (!this.sideMode) { + return { + title: `${this.node.name}: Preview`, + viewColumn: ViewColumn.One, + }; + } else { + return { + title: "Description", + viewColumn: ViewColumn.Two, + preserveFocus: true, + }; } + } - protected getWebviewContent(): string { - const button: { element: string, script: string, style: string } = { - element: ``, - script: `const button = document.getElementById('solve'); + protected getWebviewContent(): string { + const button: { element: string; script: string; style: string } = { + element: ``, + script: `const button = document.getElementById('solve'); button.onclick = () => vscode.postMessage({ command: 'ShowProblem', });`, - style: ``, - }; - const { title, url, category, difficulty, likes, dislikes, body } = this.description; - const head: string = markdownService.render(`# [${title}](${url})`); - const info: string = markdownService.render([ - `| Category | Difficulty | Likes | Dislikes |`, - `| :------: | :--------: | :---: | :------: |`, - `| ${category} | ${difficulty} | ${likes} | ${dislikes} |`, - ].join("\n")); - const tags: string = [ - `
`, - `Tags`, - markdownService.render( - this.description.tags - .map((t: string) => `[\`${t}\`](https://leetcode.com/tag/${t})`) - .join(" | "), - ), - `
`, - ].join("\n"); - const companies: string = [ - `
`, - `Companies`, - markdownService.render( - this.description.companies - .map((c: string) => `\`${c}\``) - .join(" | "), - ), - `
`, - ].join("\n"); - const links: string = markdownService.render(`[Discussion](${this.getDiscussionLink(url)}) | [Solution](${this.getSolutionLink(url)})`); - return ` + }; + const { title, url, category, difficulty, likes, dislikes, body } = this.description; + const head: string = markdownService.render(`# [${title}](${url})`); + const info: string = markdownService.render( + [ + `| Category | Difficulty | Likes | Dislikes |`, + `| :------: | :--------: | :---: | :------: |`, + `| ${category} | ${difficulty} | ${likes} | ${dislikes} |`, + ].join("\n") + ); + const tags: string = [ + `
`, + `Tags`, + markdownService.render( + this.description.tags.map((t: string) => `[\`${t}\`](https://leetcode.com/tag/${t})`).join(" | ") + ), + `
`, + ].join("\n"); + const companies: string = [ + `
`, + `Companies`, + markdownService.render(this.description.companies.map((c: string) => `\`${c}\``).join(" | ")), + `
`, + ].join("\n"); + const links: string = markdownService.render( + `[Discussion](${this.getDiscussionLink(url)}) | [Solution](${this.getSolutionLink(url)})` + ); + return ` @@ -133,85 +129,90 @@ class PreviewService extends BaseWebViewService { `; + } + + protected onDidDisposeWebview(): void { + super.onDidDisposeWebview(); + this.sideMode = false; + } + + protected async onDidReceiveMessage(message: IWebViewMessage): Promise { + switch (message.command) { + case "ShowProblem": { + await commands.executeCommand("leetcode.showProblem", this.node); + break; + } } - - protected onDidDisposeWebview(): void { - super.onDidDisposeWebview(); - this.sideMode = false; - } - - protected async onDidReceiveMessage(message: IWebViewMessage): Promise { - switch (message.command) { - case "ShowProblem": { - await commands.executeCommand("leetcode.showProblem", this.node); - break; - } - } + } + + // private async hideSideBar(): Promise { + // await commands.executeCommand("workbench.action.focusSideBar"); + // await commands.executeCommand("workbench.action.toggleSidebarVisibility"); + // } + + private parseDescription(descString: string, problem: IProblem): IDescription { + const [ + , + , + /* title */ url, + , + , + , + , + , + /* tags */ /* langs */ category, + difficulty, + likes, + dislikes, + , + , + , + , + /* accepted */ /* submissions */ /* testcase */ ...body + ] = descString.split("\n"); + return { + title: problem.name, + url, + tags: problem.tags, + companies: problem.companies, + category: category.slice(2), + difficulty: difficulty.slice(2), + likes: likes.split(": ")[1].trim(), + dislikes: dislikes.split(": ")[1].trim(), + body: body.join("\n").replace(/
[\r\n]*([^]+?)[\r\n]*<\/pre>/g, "
$1
"), + }; + } + + private getDiscussionLink(url: string): string { + const endPoint: string = getLeetCodeEndpoint(); + if (endPoint === Endpoint.LeetCodeCN) { + return url.replace("/description/", "/comments/"); + } else if (endPoint === Endpoint.LeetCode) { + return url.replace("/description/", "/discuss/?currentPage=1&orderBy=most_votes&query="); } - // private async hideSideBar(): Promise { - // await commands.executeCommand("workbench.action.focusSideBar"); - // await commands.executeCommand("workbench.action.toggleSidebarVisibility"); - // } - - private parseDescription(descString: string, problem: IProblem): IDescription { - const [ - /* title */, , - url, , - /* tags */, , - /* langs */, , - category, - difficulty, - likes, - dislikes, - /* accepted */, - /* submissions */, - /* testcase */, , - ...body - ] = descString.split("\n"); - return { - title: problem.name, - url, - tags: problem.tags, - companies: problem.companies, - category: category.slice(2), - difficulty: difficulty.slice(2), - likes: likes.split(": ")[1].trim(), - dislikes: dislikes.split(": ")[1].trim(), - body: body.join("\n").replace(/
[\r\n]*([^]+?)[\r\n]*<\/pre>/g, "
$1
"), - }; - } + return "https://leetcode.com"; + } - private getDiscussionLink(url: string): string { - const endPoint: string = getLeetCodeEndpoint(); - if (endPoint === Endpoint.LeetCodeCN) { - return url.replace("/description/", "/comments/"); - } else if (endPoint === Endpoint.LeetCode) { - return url.replace("/description/", "/discuss/?currentPage=1&orderBy=most_votes&query="); - } - - return "https://leetcode.com"; - } - - private getSolutionLink(url: string): string { - return url.replace("/description/", "/solution/"); - } + private getSolutionLink(url: string): string { + return url.replace("/description/", "/solution/"); + } } interface IDescription { - title: string; - url: string; - tags: string[]; - companies: string[]; - category: string; - difficulty: string; - likes: string; - dislikes: string; - body: string; + title: string; + url: string; + tags: string[]; + companies: string[]; + category: string; + difficulty: string; + likes: string; + dislikes: string; + body: string; } interface IWebViewMessage { - command: string; + command: string; } export const previewService: PreviewService = new PreviewService(); diff --git a/src/service/SolutionService.ts b/src/service/SolutionService.ts index 6a99a6f..d9da011 100644 --- a/src/service/SolutionService.ts +++ b/src/service/SolutionService.ts @@ -7,55 +7,54 @@ * Copyright (c) 2022 ccagml . All rights reserved. */ - import { ViewColumn } from "vscode"; import { previewService } from "./PreviewService"; import { BaseWebViewService } from "./BaseWebviewService"; import { markdownService } from "./MarkdownService"; import { IWebViewOption } from "../model/Model"; - - class SolutionService extends BaseWebViewService { - protected readonly viewType: string = "leetcode.solution"; - private problemName: string; - private solution: Solution; + protected readonly viewType: string = "leetcode.solution"; + private problemName: string; + private solution: Solution; - public show(solutionString: string): void { - this.solution = this.parseSolution(solutionString); - this.showWebviewInternal(); - } + public show(solutionString: string): void { + this.solution = this.parseSolution(solutionString); + this.showWebviewInternal(); + } - protected getWebviewOption(): IWebViewOption { - if (previewService.isSideMode()) { - return { - title: "Solution", - viewColumn: ViewColumn.Two, - preserveFocus: true, - }; - } else { - return { - title: `Solution: ${this.problemName}`, - viewColumn: ViewColumn.One, - }; - } + protected getWebviewOption(): IWebViewOption { + if (previewService.isSideMode()) { + return { + title: "Solution", + viewColumn: ViewColumn.Two, + preserveFocus: true, + }; + } else { + return { + title: `Solution: ${this.problemName}`, + viewColumn: ViewColumn.One, + }; } + } - protected getWebviewContent(): string { - const styles: string = markdownService.getStyles(); - const { title, url, lang, author, votes } = this.solution; - const head: string = markdownService.render(`# [${title}](${url})`); - const auth: string = `[${author}](https://leetcode.com/${author}/)`; - const info: string = markdownService.render([ - `| Language | Author | Votes |`, - `| :------: | :------: | :------: |`, - `| ${lang} | ${auth} | ${votes} |`, - ].join("\n")); - const body: string = markdownService.render(this.solution.body, { - lang: this.solution.lang, - host: "https://discuss.leetcode.com/", - }); - return ` + protected getWebviewContent(): string { + const styles: string = markdownService.getStyles(); + const { title, url, lang, author, votes } = this.solution; + const head: string = markdownService.render(`# [${title}](${url})`); + const auth: string = `[${author}](https://leetcode.com/${author}/)`; + const info: string = markdownService.render( + [ + `| Language | Author | Votes |`, + `| :------: | :------: | :------: |`, + `| ${lang} | ${auth} | ${votes} |`, + ].join("\n") + ); + const body: string = markdownService.render(this.solution.body, { + lang: this.solution.lang, + host: "https://discuss.leetcode.com/", + }); + return ` @@ -69,35 +68,35 @@ class SolutionService extends BaseWebViewService { `; - } + } - protected onDidDisposeWebview(): void { - super.onDidDisposeWebview(); - } + protected onDidDisposeWebview(): void { + super.onDidDisposeWebview(); + } - private parseSolution(raw: string): Solution { - raw = raw.slice(1); // skip first empty line - [this.problemName, raw] = raw.split(/\n\n([^]+)/); // parse problem name and skip one line - const solution: Solution = new Solution(); - // [^] matches everything including \n, yet can be replaced by . in ES2018's `m` flag - [solution.title, raw] = raw.split(/\n\n([^]+)/); - [solution.url, raw] = raw.split(/\n\n([^]+)/); - [solution.lang, raw] = raw.match(/\* Lang:\s+(.+)\n([^]+)/)!.slice(1); - [solution.author, raw] = raw.match(/\* Author:\s+(.+)\n([^]+)/)!.slice(1); - [solution.votes, raw] = raw.match(/\* Votes:\s+(\d+)\n\n([^]+)/)!.slice(1); - solution.body = raw; - return solution; - } + private parseSolution(raw: string): Solution { + raw = raw.slice(1); // skip first empty line + [this.problemName, raw] = raw.split(/\n\n([^]+)/); // parse problem name and skip one line + const solution: Solution = new Solution(); + // [^] matches everything including \n, yet can be replaced by . in ES2018's `m` flag + [solution.title, raw] = raw.split(/\n\n([^]+)/); + [solution.url, raw] = raw.split(/\n\n([^]+)/); + [solution.lang, raw] = raw.match(/\* Lang:\s+(.+)\n([^]+)/)!.slice(1); + [solution.author, raw] = raw.match(/\* Author:\s+(.+)\n([^]+)/)!.slice(1); + [solution.votes, raw] = raw.match(/\* Votes:\s+(\d+)\n\n([^]+)/)!.slice(1); + solution.body = raw; + return solution; + } } // tslint:disable-next-line:max-classes-per-file class Solution { - public title: string = ""; - public url: string = ""; - public lang: string = ""; - public author: string = ""; - public votes: string = ""; - public body: string = ""; // Markdown supported + public title: string = ""; + public url: string = ""; + public lang: string = ""; + public author: string = ""; + public votes: string = ""; + public body: string = ""; // Markdown supported } export const solutionService: SolutionService = new SolutionService(); diff --git a/src/service/StatusBarService.ts b/src/service/StatusBarService.ts index 07b2fea..5d379b8 100644 --- a/src/service/StatusBarService.ts +++ b/src/service/StatusBarService.ts @@ -7,7 +7,6 @@ * Copyright (c) 2022 ccagml . All rights reserved. */ - import { ConfigurationChangeEvent, Disposable, workspace, StatusBarItem, window } from "vscode"; import { UserStatus, userContestRanKingBase } from "../model/Model"; import { enableStatusBar } from "../utils/ConfigUtils"; @@ -16,121 +15,127 @@ import { executeService } from "./ExecuteService"; // 状态栏工具 class StatusBarService implements Disposable { - private instance: StatusBarItem; - private configurationChangeListener: Disposable; - private userStatus: UserStatus; - private currentUser: string | undefined; - private currentUserContestInfo: userContestRanKingBase | undefined; - - // 获取竞赛分 - public getUserContestScore(): number { - if (this.currentUserContestInfo && this.currentUserContestInfo.rating > 0) { - return this.currentUserContestInfo.rating; - } - return 0; - } - - public getUserContestInfo(): userContestRanKingBase | undefined { - return this.currentUserContestInfo; - } - - // 获取用户名 - public getUser(): string | undefined { - return this.currentUser; - } - - // 获取登录状态 - public getStatus(): UserStatus { - return this.userStatus; - } - - public async getLoginStatus(): Promise { - try { - const result: string = await executeService.getUserInfo(); - this.currentUser = this.tryParseUserName(result); - this.userStatus = UserStatus.SignedIn; - if (this.currentUser == undefined) { - this.userStatus = UserStatus.SignedOut; - } - } catch (error) { - this.currentUser = undefined; - this.userStatus = UserStatus.SignedOut; - } finally { - eventService.emit("statusChanged", this.userStatus, this.currentUser); - } - } - private tryParseUserName(output: string): string | undefined { - let successMatch; - try { - successMatch = JSON.parse(output); - } catch (e) { - successMatch = {}; - } - if (successMatch.code == 100) { - return successMatch.user_name; - } - return undefined; + private instance: StatusBarItem; + private configurationChangeListener: Disposable; + private userStatus: UserStatus; + private currentUser: string | undefined; + private currentUserContestInfo: userContestRanKingBase | undefined; + + // 获取竞赛分 + public getUserContestScore(): number { + if (this.currentUserContestInfo && this.currentUserContestInfo.rating > 0) { + return this.currentUserContestInfo.rating; } - - - constructor() { - this.instance = window.createStatusBarItem(); - this.setStatusBarVisibility(); - this.currentUser = undefined; + return 0; + } + + public getUserContestInfo(): userContestRanKingBase | undefined { + return this.currentUserContestInfo; + } + + // 获取用户名 + public getUser(): string | undefined { + return this.currentUser; + } + + // 获取登录状态 + public getStatus(): UserStatus { + return this.userStatus; + } + + public async getLoginStatus(): Promise { + try { + const result: string = await executeService.getUserInfo(); + this.currentUser = this.tryParseUserName(result); + this.userStatus = UserStatus.SignedIn; + if (this.currentUser == undefined) { this.userStatus = UserStatus.SignedOut; - - this.configurationChangeListener = workspace.onDidChangeConfiguration((event: ConfigurationChangeEvent) => { - if (event.affectsConfiguration("leetcode-problem-rating.enableStatusBar")) { - this.setStatusBarVisibility(); - } - }, this); - } - - // 更新状态栏的数据 - public update_instance(status: UserStatus, user?: string, UserContestInfo?: userContestRanKingBase | undefined): void { - switch (status) { - case UserStatus.SignedIn: - if (UserContestInfo && UserContestInfo.attendedContestsCount > 0) { - this.instance.text = `用户: ${user}, 积分: ${Math.floor(UserContestInfo.rating)}, 名次: ${UserContestInfo.localRanking} / ${UserContestInfo.localTotalParticipants} (${UserContestInfo.topPercentage}%), 全部名次: ${UserContestInfo.globalRanking} / ${UserContestInfo.globalTotalParticipants}`; - } else { - this.instance.text = `user: ${user}`; - } - break; - case UserStatus.SignedOut: - default: - this.instance.text = ""; - break; - } + } + } catch (error) { + this.currentUser = undefined; + this.userStatus = UserStatus.SignedOut; + } finally { + eventService.emit("statusChanged", this.userStatus, this.currentUser); } - - public update_status(status: UserStatus, user?: string) { - this.userStatus = status; - this.currentUser = user; - } - public update_UserContestInfo(UserContestInfo?: userContestRanKingBase | undefined) { - this.currentUserContestInfo = UserContestInfo; + } + private tryParseUserName(output: string): string | undefined { + let successMatch; + try { + successMatch = JSON.parse(output); + } catch (e) { + successMatch = {}; } - - // 更新数据 - public update(): void { - this.update_instance(this.userStatus, this.currentUser, this.currentUserContestInfo); + if (successMatch.code == 100) { + return successMatch.user_name; } + return undefined; + } - //销毁数据 - public dispose(): void { - this.instance.dispose(); - this.configurationChangeListener.dispose(); - } + constructor() { + this.instance = window.createStatusBarItem(); + this.setStatusBarVisibility(); + this.currentUser = undefined; + this.userStatus = UserStatus.SignedOut; - // 设置可见性 - private setStatusBarVisibility(): void { - if (enableStatusBar()) { - this.instance.show(); + this.configurationChangeListener = workspace.onDidChangeConfiguration((event: ConfigurationChangeEvent) => { + if (event.affectsConfiguration("leetcode-problem-rating.enableStatusBar")) { + this.setStatusBarVisibility(); + } + }, this); + } + + // 更新状态栏的数据 + public update_instance( + status: UserStatus, + user?: string, + UserContestInfo?: userContestRanKingBase | undefined + ): void { + switch (status) { + case UserStatus.SignedIn: + if (UserContestInfo && UserContestInfo.attendedContestsCount > 0) { + this.instance.text = `用户: ${user}, 积分: ${Math.floor(UserContestInfo.rating)}, 名次: ${ + UserContestInfo.localRanking + } / ${UserContestInfo.localTotalParticipants} (${UserContestInfo.topPercentage}%), 全部名次: ${ + UserContestInfo.globalRanking + } / ${UserContestInfo.globalTotalParticipants}`; } else { - this.instance.hide(); + this.instance.text = `user: ${user}`; } + break; + case UserStatus.SignedOut: + default: + this.instance.text = ""; + break; } - + } + + public update_status(status: UserStatus, user?: string) { + this.userStatus = status; + this.currentUser = user; + } + public update_UserContestInfo(UserContestInfo?: userContestRanKingBase | undefined) { + this.currentUserContestInfo = UserContestInfo; + } + + // 更新数据 + public update(): void { + this.update_instance(this.userStatus, this.currentUser, this.currentUserContestInfo); + } + + //销毁数据 + public dispose(): void { + this.instance.dispose(); + this.configurationChangeListener.dispose(); + } + + // 设置可见性 + private setStatusBarVisibility(): void { + if (enableStatusBar()) { + this.instance.show(); + } else { + this.instance.hide(); + } + } } export const statusBarService: StatusBarService = new StatusBarService(); diff --git a/src/service/SubmissionService.ts b/src/service/SubmissionService.ts index 97611cd..9d596d1 100644 --- a/src/service/SubmissionService.ts +++ b/src/service/SubmissionService.ts @@ -7,7 +7,6 @@ * Copyright (c) 2022 ccagml . All rights reserved. */ - import { ViewColumn, commands } from "vscode"; import { BaseWebViewService } from "./BaseWebviewService"; import { markdownService } from "./MarkdownService"; @@ -16,44 +15,34 @@ import { IWebViewOption } from "../model/Model"; import { promptHintMessage } from "../utils/OutputUtils"; class SubmissionService extends BaseWebViewService { + protected readonly viewType: string = "leetcode.submission"; + private result: IResult; - protected readonly viewType: string = "leetcode.submission"; - private result: IResult; - - public show(resultString: string): void { - this.result = this.parseResult(resultString); - this.showWebviewInternal(); - this.showKeybindingsHint(); - } - public getSubmitEvent(): ISubmitEvent { - return this.result.system_message as unknown as ISubmitEvent; - } + public show(resultString: string): void { + this.result = this.parseResult(resultString); + this.showWebviewInternal(); + this.showKeybindingsHint(); + } + public getSubmitEvent(): ISubmitEvent { + return this.result.system_message as unknown as ISubmitEvent; + } - protected getWebviewOption(): IWebViewOption { - return { - title: "Submission", - viewColumn: ViewColumn.Two, - }; - } + protected getWebviewOption(): IWebViewOption { + return { + title: "Submission", + viewColumn: ViewColumn.Two, + }; + } - protected getWebviewContent(): string { - const styles: string = markdownService.getStyles(); - const title: string = `## ${this.result.messages[0]}`; - const messages: string[] = this.result.messages.slice(1).map((m: string) => `* ${m}`); - const sections: string[] = Object.keys(this.result) - .filter((key: string) => (key !== "messages" && key !== "system_message")) - .map((key: string) => [ - `### ${key}`, - "```", - this.result[key].join("\n"), - "```", - ].join("\n")); - const body: string = markdownService.render([ - title, - ...messages, - ...sections, - ].join("\n")); - return ` + protected getWebviewContent(): string { + const styles: string = markdownService.getStyles(); + const title: string = `## ${this.result.messages[0]}`; + const messages: string[] = this.result.messages.slice(1).map((m: string) => `* ${m}`); + const sections: string[] = Object.keys(this.result) + .filter((key: string) => key !== "messages" && key !== "system_message") + .map((key: string) => [`### ${key}`, "```", this.result[key].join("\n"), "```"].join("\n")); + const body: string = markdownService.render([title, ...messages, ...sections].join("\n")); + return ` @@ -67,35 +56,34 @@ class SubmissionService extends BaseWebViewService { `; - } + } - protected onDidDisposeWebview(): void { - super.onDidDisposeWebview(); - } + protected onDidDisposeWebview(): void { + super.onDidDisposeWebview(); + } - private async showKeybindingsHint(): Promise { - let that = this; - await promptHintMessage( - "hint.commandShortcut", - 'You can customize shortcut key bindings in File > Preferences > Keyboard Shortcuts with query "leetcode".', - "Open Keybindings", - (): Promise => that.openKeybindingsEditor("leetcode solution"), - ); - } + private async showKeybindingsHint(): Promise { + let that = this; + await promptHintMessage( + "hint.commandShortcut", + 'You can customize shortcut key bindings in File > Preferences > Keyboard Shortcuts with query "leetcode".', + "Open Keybindings", + (): Promise => that.openKeybindingsEditor("leetcode solution") + ); + } - private async openKeybindingsEditor(query?: string): Promise { - await commands.executeCommand("workbench.action.openGlobalKeybindings", query); - } + private async openKeybindingsEditor(query?: string): Promise { + await commands.executeCommand("workbench.action.openGlobalKeybindings", query); + } - private parseResult(raw: string): IResult { - return JSON.parse(raw); - } + private parseResult(raw: string): IResult { + return JSON.parse(raw); + } } interface IResult { - [key: string]: string[]; - messages: string[]; + [key: string]: string[]; + messages: string[]; } - export const submissionService: SubmissionService = new SubmissionService(); diff --git a/src/service/TreeDataService.ts b/src/service/TreeDataService.ts index 1ed3ad8..9eab305 100644 --- a/src/service/TreeDataService.ts +++ b/src/service/TreeDataService.ts @@ -7,11 +7,18 @@ * Copyright (c) 2022 ccagml . All rights reserved. */ - // import * as os from "os"; import * as path from "path"; import * as vscode from "vscode"; -import { Category, defaultProblem, IScoreData, ProblemState, SearchSetType, ISubmitEvent, DialogType } from "../model/Model"; +import { + Category, + defaultProblem, + IScoreData, + ProblemState, + SearchSetType, + ISubmitEvent, + DialogType, +} from "../model/Model"; import { treeViewController } from "../controller/TreeViewController"; import { NodeModel } from "../model/NodeModel"; import { statusBarService } from "./StatusBarService"; @@ -22,168 +29,181 @@ import { executeService } from "./ExecuteService"; import { promptForOpenOutputChannel } from "../utils/OutputUtils"; export class TreeDataService implements vscode.TreeDataProvider { - - private context: vscode.ExtensionContext; - private onDidChangeTreeDataEvent: vscode.EventEmitter = new vscode.EventEmitter(); - // tslint:disable-next-line:member-ordering - public readonly onDidChangeTreeData: vscode.Event = this.onDidChangeTreeDataEvent.event; - - public initialize(context: vscode.ExtensionContext): void { - this.context = context; + private context: vscode.ExtensionContext; + private onDidChangeTreeDataEvent: vscode.EventEmitter = new vscode.EventEmitter< + NodeModel | undefined | null + >(); + // tslint:disable-next-line:member-ordering + public readonly onDidChangeTreeData: vscode.Event = this.onDidChangeTreeDataEvent.event; + + public initialize(context: vscode.ExtensionContext): void { + this.context = context; + } + + public checkSubmit(e: ISubmitEvent) { + treeViewController.checkSubmit(e); + } + + public cleanUserScore() { + treeViewController.clearUserScore(); + } + + public async refresh(): Promise { + await treeViewController.refreshCache(); + this.onDidChangeTreeDataEvent.fire(null); + await treeViewController.refreshCheck(); + } + + public getTreeItem(element: NodeModel): vscode.TreeItem | Thenable { + if (element.id === "notSignIn") { + return { + label: element.name, + collapsibleState: vscode.TreeItemCollapsibleState.None, + command: { + command: "leetcode.signin", + title: "未登录", + }, + }; } - public checkSubmit(e: ISubmitEvent) { - treeViewController.checkSubmit(e); + let contextValue: string; + if (element.isProblem) { + contextValue = element.isFavorite ? "problem-favorite" : "problem"; + } else { + contextValue = element.id.toLowerCase(); } - public cleanUserScore() { - treeViewController.clearUserScore(); - } - - public async refresh(): Promise { - await treeViewController.refreshCache(); - this.onDidChangeTreeDataEvent.fire(null); - await treeViewController.refreshCheck(); - } - - public getTreeItem(element: NodeModel): vscode.TreeItem | Thenable { - if (element.id === "notSignIn") { - return { - label: element.name, - collapsibleState: vscode.TreeItemCollapsibleState.None, - command: { - command: "leetcode.signin", - title: "未登录", - }, - }; - } - - let contextValue: string; - if (element.isProblem) { - contextValue = element.isFavorite ? "problem-favorite" : "problem"; - } else { - contextValue = element.id.toLowerCase(); - } - - const result: vscode.TreeItem | Thenable = { - label: element.isProblem ? (element.score > "0" ? "[score:" + (element.score) + "]" : "") + `ID:${element.id}.${element.name} ` : element.name, - tooltip: this.getSubCategoryTooltip(element), - collapsibleState: element.isProblem ? vscode.TreeItemCollapsibleState.None : vscode.TreeItemCollapsibleState.Collapsed, - iconPath: this.parseIconPathFromProblemState(element), - command: element.isProblem ? element.previewCommand : undefined, - resourceUri: element.uri, - contextValue, - }; - return result; + const result: vscode.TreeItem | Thenable = { + label: element.isProblem + ? (element.score > "0" ? "[score:" + element.score + "]" : "") + `ID:${element.id}.${element.name} ` + : element.name, + tooltip: this.getSubCategoryTooltip(element), + collapsibleState: element.isProblem + ? vscode.TreeItemCollapsibleState.None + : vscode.TreeItemCollapsibleState.Collapsed, + iconPath: this.parseIconPathFromProblemState(element), + command: element.isProblem ? element.previewCommand : undefined, + resourceUri: element.uri, + contextValue, + }; + return result; + } + + public getChildren(element?: NodeModel | undefined): vscode.ProviderResult { + if (!statusBarService.getUser()) { + return [ + new NodeModel( + Object.assign({}, defaultProblem, { + id: "notSignIn", + name: "未登录", + }), + false + ), + ]; } - - public getChildren(element?: NodeModel | undefined): vscode.ProviderResult { - if (!statusBarService.getUser()) { - return [ - new NodeModel(Object.assign({}, defaultProblem, { - id: "notSignIn", - name: "未登录", - }), false), - ]; + if (!element) { + // Root view + return treeViewController.getRootNodes(); + } else { + if (element.isSearchResult) { + switch (element.id) { + case SearchSetType.ScoreRange: + return treeViewController.getScoreRangeNodes(element.input); + break; + case SearchSetType.Context: + return treeViewController.getContextNodes(element.input); + break; + case SearchSetType.Day: + return treeViewController.getDayNodes(element); + break; + default: + break; } - if (!element) { // Root view - return treeViewController.getRootNodes(); - } else { - if (element.isSearchResult) { - switch (element.id) { - case SearchSetType.ScoreRange: - return treeViewController.getScoreRangeNodes(element.input); - break; - case SearchSetType.Context: - return treeViewController.getContextNodes(element.input); - break; - case SearchSetType.Day: - return treeViewController.getDayNodes(element); - break; - default: - break; - } - return []; - } else { - switch (element.id) { // First-level - case Category.All: - return treeViewController.getAllNodes(); - case Category.Favorite: - return treeViewController.getFavoriteNodes(); - case Category.Difficulty: - return treeViewController.getAllDifficultyNodes(); - case Category.Tag: - return treeViewController.getAllTagNodes(); - case Category.Company: - return treeViewController.getAllCompanyNodes(); - case Category.Score: - return treeViewController.getAllScoreNodes(element.user_score); - case Category.Choice: - return treeViewController.getAllChoiceNodes(); - default: - if (element.isProblem) { - return []; - } - return treeViewController.getChildrenNodesById(element.id); - } + return []; + } else { + switch ( + element.id // First-level + ) { + case Category.All: + return treeViewController.getAllNodes(); + case Category.Favorite: + return treeViewController.getFavoriteNodes(); + case Category.Difficulty: + return treeViewController.getAllDifficultyNodes(); + case Category.Tag: + return treeViewController.getAllTagNodes(); + case Category.Company: + return treeViewController.getAllCompanyNodes(); + case Category.Score: + return treeViewController.getAllScoreNodes(element.user_score); + case Category.Choice: + return treeViewController.getAllChoiceNodes(); + default: + if (element.isProblem) { + return []; } - + return treeViewController.getChildrenNodesById(element.id); } + } } - - public getChoiceData() { - return choiceDao.getChoiceData(); + } + + public getChoiceData() { + return choiceDao.getChoiceData(); + } + public getTagsData(fid: string): Array { + return tagsDao.getTagsData(fid) || ["Unknown"]; + } + + // 返回题目id的数据 + public getScoreData(): Map { + return scoreDao.getScoreData(); + } + // 在线获取题目数据 + public async getScoreDataOnline() { + let stringData = await executeService.getScoreDataOnline(); + let objData; + try { + objData = JSON.parse(stringData); + } catch (error) { + objData = {}; } - public getTagsData(fid: string): Array { - return tagsDao.getTagsData(fid) || ["Unknown"]; + if (objData.code == 101) { + promptForOpenOutputChannel( + "从 https://zerotrac.github.io/leetcode_problem_rating/data.json 获取数据出错", + DialogType.info + ); + objData = {}; } + return scoreDao.getScoreData(objData.data); + } - // 返回题目id的数据 - public getScoreData(): Map { - return scoreDao.getScoreData(); + private parseIconPathFromProblemState(element: NodeModel): string { + if (!element.isProblem) { + return ""; } - // 在线获取题目数据 - public async getScoreDataOnline() { - let stringData = await executeService.getScoreDataOnline(); - let objData; - try { - objData = JSON.parse(stringData); - } catch (error) { - objData = {}; - } - if (objData.code == 101) { - promptForOpenOutputChannel("从 https://zerotrac.github.io/leetcode_problem_rating/data.json 获取数据出错", DialogType.info); - objData = {}; - } - return scoreDao.getScoreData(objData.data); - } - - private parseIconPathFromProblemState(element: NodeModel): string { - if (!element.isProblem) { - return ""; - } - switch (element.state) { - case ProblemState.AC: - return this.context.asAbsolutePath(path.join("resources", "check.png")); - case ProblemState.NotAC: - return this.context.asAbsolutePath(path.join("resources", "x.png")); - case ProblemState.Unknown: - if (element.locked) { - return this.context.asAbsolutePath(path.join("resources", "lock.png")); - } - return this.context.asAbsolutePath(path.join("resources", "blank.png")); - default: - return ""; + switch (element.state) { + case ProblemState.AC: + return this.context.asAbsolutePath(path.join("resources", "check.png")); + case ProblemState.NotAC: + return this.context.asAbsolutePath(path.join("resources", "x.png")); + case ProblemState.Unknown: + if (element.locked) { + return this.context.asAbsolutePath(path.join("resources", "lock.png")); } + return this.context.asAbsolutePath(path.join("resources", "blank.png")); + default: + return ""; } + } - private getSubCategoryTooltip(element: NodeModel): string { - // return '' unless it is a sub-category node - if (element.isProblem || element.id === "ROOT" || element.id in Category) { - return ""; - } - return ""; + private getSubCategoryTooltip(element: NodeModel): string { + // return '' unless it is a sub-category node + if (element.isProblem || element.id === "ROOT" || element.id in Category) { + return ""; } + return ""; + } } export const treeDataService: TreeDataService = new TreeDataService(); diff --git a/src/service/TreeItemDecorationService.ts b/src/service/TreeItemDecorationService.ts index 98ce0d1..cc87975 100644 --- a/src/service/TreeItemDecorationService.ts +++ b/src/service/TreeItemDecorationService.ts @@ -7,81 +7,86 @@ * Copyright (c) 2022 ccagml . All rights reserved. */ - import { URLSearchParams } from "url"; -import { FileDecoration, FileDecorationProvider, ProviderResult, ThemeColor, Uri, workspace, WorkspaceConfiguration } from "vscode"; +import { + FileDecoration, + FileDecorationProvider, + ProviderResult, + ThemeColor, + Uri, + workspace, + WorkspaceConfiguration, +} from "vscode"; export class TreeItemDecorationService implements FileDecorationProvider { - private readonly ITEM_COLOR: { [key: string]: ThemeColor } = { - easy: new ThemeColor("charts.green"), - medium: new ThemeColor("charts.yellow"), - hard: new ThemeColor("charts.red"), - - green: new ThemeColor("charts.green"), // 图表中绿色元素的颜色。 // 低于玩家分数 200分 - blue: new ThemeColor("charts.blue"), // 图表中蓝色元素的颜色。 // 低于玩家分数 50 - 199分 - purple: new ThemeColor("charts.purple"), // 图表中紫色元素的颜色。// 高于玩家50 到低于49 - yellow: new ThemeColor("charts.yellow"), // 图表中黄色元素的颜色。 // 高于玩家50 - 199 - red: new ThemeColor("charts.red"), // 图表中红色元素的颜色。 // 高于200 + private readonly ITEM_COLOR: { [key: string]: ThemeColor } = { + easy: new ThemeColor("charts.green"), + medium: new ThemeColor("charts.yellow"), + hard: new ThemeColor("charts.red"), - }; - - public provideFileDecoration(uri: Uri): ProviderResult { - if (!this.isDifficultyBadgeEnabled()) { - return; - } + green: new ThemeColor("charts.green"), // 图表中绿色元素的颜色。 // 低于玩家分数 200分 + blue: new ThemeColor("charts.blue"), // 图表中蓝色元素的颜色。 // 低于玩家分数 50 - 199分 + purple: new ThemeColor("charts.purple"), // 图表中紫色元素的颜色。// 高于玩家50 到低于49 + yellow: new ThemeColor("charts.yellow"), // 图表中黄色元素的颜色。 // 高于玩家50 - 199 + red: new ThemeColor("charts.red"), // 图表中红色元素的颜色。 // 高于200 + }; - if (uri.scheme !== "leetcode" && uri.authority !== "problems") { - return; - } + public provideFileDecoration(uri: Uri): ProviderResult { + if (!this.isDifficultyBadgeEnabled()) { + return; + } - const params: URLSearchParams = new URLSearchParams(uri.query); - // const difficulty: string = params.get("difficulty")!.toLowerCase(); - const score: string = params.get("score") || "0"; - const user_score: string = params.get("user_score") || "0"; + if (uri.scheme !== "leetcode" && uri.authority !== "problems") { + return; + } - const file_color: FileDecoration = { - // badge: score > "0" ? "" : this.DIFFICULTY_BADGE_LABEL[difficulty], - // color: this.ITEM_COLOR[difficulty], - // tooltip: score > "0" ? score : "0" - }; - const score_num = Number(score); - const user_score_num = Number(user_score); - if (score_num > 0) { - if (user_score_num > 0) { - const diff_num = score_num - user_score_num; - // green: new ThemeColor("charts.green"), // 图表中绿色元素的颜色。 // 低于玩家分数 200分 - // blue: new ThemeColor("charts.blue"), // 图表中蓝色元素的颜色。 // 低于玩家分数 50 - 199分 - // purple: new ThemeColor("charts.purple"), // 图表中紫色元素的颜色。// 高于玩家50 到低于49 - // yellow: new ThemeColor("charts.yellow"), // 图表中黄色元素的颜色。 // 高于玩家50 - 199 - // red: new ThemeColor("charts.red"), // 图表中红色元素的颜色。 // 高于200 - if (diff_num < -200) { - file_color.color = this.ITEM_COLOR.green; - file_color.tooltip = "秒杀难度"; - } else if (diff_num < -50) { - file_color.color = this.ITEM_COLOR.blue; - file_color.tooltip = "热身难度"; - } else if (diff_num < 50) { - file_color.color = this.ITEM_COLOR.purple; - file_color.tooltip = "普通难度"; - } else if (diff_num < 199) { - file_color.color = this.ITEM_COLOR.yellow; - file_color.tooltip = "吃力难度"; - } else { - file_color.color = this.ITEM_COLOR.red; - file_color.tooltip = "劝退难度"; - } - } else { - file_color.tooltip = "还没有竞赛分"; - } + const params: URLSearchParams = new URLSearchParams(uri.query); + // const difficulty: string = params.get("difficulty")!.toLowerCase(); + const score: string = params.get("score") || "0"; + const user_score: string = params.get("user_score") || "0"; + const file_color: FileDecoration = { + // badge: score > "0" ? "" : this.DIFFICULTY_BADGE_LABEL[difficulty], + // color: this.ITEM_COLOR[difficulty], + // tooltip: score > "0" ? score : "0" + }; + const score_num = Number(score); + const user_score_num = Number(user_score); + if (score_num > 0) { + if (user_score_num > 0) { + const diff_num = score_num - user_score_num; + // green: new ThemeColor("charts.green"), // 图表中绿色元素的颜色。 // 低于玩家分数 200分 + // blue: new ThemeColor("charts.blue"), // 图表中蓝色元素的颜色。 // 低于玩家分数 50 - 199分 + // purple: new ThemeColor("charts.purple"), // 图表中紫色元素的颜色。// 高于玩家50 到低于49 + // yellow: new ThemeColor("charts.yellow"), // 图表中黄色元素的颜色。 // 高于玩家50 - 199 + // red: new ThemeColor("charts.red"), // 图表中红色元素的颜色。 // 高于200 + if (diff_num < -200) { + file_color.color = this.ITEM_COLOR.green; + file_color.tooltip = "秒杀难度"; + } else if (diff_num < -50) { + file_color.color = this.ITEM_COLOR.blue; + file_color.tooltip = "热身难度"; + } else if (diff_num < 50) { + file_color.color = this.ITEM_COLOR.purple; + file_color.tooltip = "普通难度"; + } else if (diff_num < 199) { + file_color.color = this.ITEM_COLOR.yellow; + file_color.tooltip = "吃力难度"; + } else { + file_color.color = this.ITEM_COLOR.red; + file_color.tooltip = "劝退难度"; } - return file_color; + } else { + file_color.tooltip = "还没有竞赛分"; + } } + return file_color; + } - private isDifficultyBadgeEnabled(): boolean { - const configuration: WorkspaceConfiguration = workspace.getConfiguration("leetcode-problem-rating"); - return configuration.get("colorizeProblems", false); - } + private isDifficultyBadgeEnabled(): boolean { + const configuration: WorkspaceConfiguration = workspace.getConfiguration("leetcode-problem-rating"); + return configuration.get("colorizeProblems", false); + } } export const treeItemDecorationService: TreeItemDecorationService = new TreeItemDecorationService(); diff --git a/src/utils/CliUtils.ts b/src/utils/CliUtils.ts index 07d8d2e..ffce86d 100644 --- a/src/utils/CliUtils.ts +++ b/src/utils/CliUtils.ts @@ -7,93 +7,111 @@ * Copyright (c) 2022 ccagml . All rights reserved. */ - import * as cp from "child_process"; import * as vscode from "vscode"; import { logOutput } from "./OutputUtils"; import * as systemUtils from "./SystemUtils"; interface IExecError extends Error { - result?: string; + result?: string; } -export async function executeCommand(command: string, args: string[], options: cp.SpawnOptions = { shell: true }): Promise { - return new Promise((resolve: (res: string) => void, reject: (e: Error) => void): void => { - let result: string = ""; - let childProc: cp.ChildProcess; - if (systemUtils.useVscodeNode() && command == "node") { - let newargs: string[] = []; - command = args[0]; - for (let arg_index = 1; arg_index < args.length; arg_index++) { - newargs.push(args[arg_index]); - } - let new_opt = { silent: true, ...options, env: createEnvOption() }; - if (false) { - new_opt["execArgv"] = ['--inspect=43210']; - } - childProc = cp.fork(command, newargs, new_opt); - } else { - childProc = cp.spawn(command, args, { ...options, env: createEnvOption() }); - } - - childProc.stdout?.on("data", (data: string | Buffer) => { - data = data.toString(); - result = result.concat(data); - logOutput.append(data); - }); +export async function executeCommand( + command: string, + args: string[], + options: cp.SpawnOptions = { shell: true } +): Promise { + return new Promise((resolve: (res: string) => void, reject: (e: Error) => void): void => { + let result: string = ""; + let childProc: cp.ChildProcess; + if (systemUtils.useVscodeNode() && command == "node") { + let newargs: string[] = []; + command = args[0]; + for (let arg_index = 1; arg_index < args.length; arg_index++) { + newargs.push(args[arg_index]); + } + let new_opt = { silent: true, ...options, env: createEnvOption() }; + if (false) { + new_opt["execArgv"] = ["--inspect=43210"]; + } + childProc = cp.fork(command, newargs, new_opt); + } else { + childProc = cp.spawn(command, args, { + ...options, + env: createEnvOption(), + }); + } - childProc.stderr?.on("data", (data: string | Buffer) => logOutput.append(data.toString())); + childProc.stdout?.on("data", (data: string | Buffer) => { + data = data.toString(); + result = result.concat(data); + logOutput.append(data); + }); - childProc.on("error", reject); + childProc.stderr?.on("data", (data: string | Buffer) => logOutput.append(data.toString())); - childProc.on("close", (code: number) => { + childProc.on("error", reject); - let try_result_json; - try { - try_result_json = JSON.parse(result); - } catch (e) { - try_result_json; - } - if (code !== 0 || (try_result_json ? try_result_json.code < 0 : (result.indexOf("ERROR") > -1))) { - const error: IExecError = new Error(`Command "${command} ${args.toString()}" failed with exit code "${code}".`); - if (result) { - error.result = result; - } - reject(error); - } else { - resolve(result); - } - }); + childProc.on("close", (code: number) => { + let try_result_json; + try { + try_result_json = JSON.parse(result); + } catch (e) { + try_result_json; + } + if (code !== 0 || (try_result_json ? try_result_json.code < 0 : result.indexOf("ERROR") > -1)) { + const error: IExecError = new Error(`Command "${command} ${args.toString()}" failed with exit code "${code}".`); + if (result) { + error.result = result; + } + reject(error); + } else { + resolve(result); + } }); + }); } -export async function executeCommandWithProgress(message: string, command: string, args: string[], options: cp.SpawnOptions = { shell: true }): Promise { - let result: string = ""; - await vscode.window.withProgress({ location: vscode.ProgressLocation.Notification }, async (p: vscode.Progress<{}>) => { - return new Promise(async (resolve: () => void, reject: (e: Error) => void): Promise => { - p.report({ message }); - try { - result = await executeCommand(command, args, options); - resolve(); - } catch (e) { - reject(e); - } - }); - }); - return result; +export async function executeCommandWithProgress( + message: string, + command: string, + args: string[], + options: cp.SpawnOptions = { shell: true } +): Promise { + let result: string = ""; + await vscode.window.withProgress( + { location: vscode.ProgressLocation.Notification }, + async (p: vscode.Progress<{}>) => { + return new Promise(async (resolve: () => void, reject: (e: Error) => void): Promise => { + p.report({ message }); + try { + result = await executeCommand(command, args, options); + resolve(); + } catch (e) { + reject(e); + } + }); + } + ); + return result; +} + +function childLCPTCTX(): string { + return JSON.stringify(logOutput.getLCPTCTXAll()); } // clone process.env and add http proxy export function createEnvOption(): {} { - const proxy: string | undefined = getHttpAgent(); - if (proxy) { - const env: any = Object.create(process.env); - env.http_proxy = proxy; - return env; - } - return process.env; + const proxy: string | undefined = getHttpAgent(); + const env: any = Object.create(process.env); + if (proxy) { + env.http_proxy = proxy; + return env; + } + env.ccagml = childLCPTCTX(); + return env; } function getHttpAgent(): string | undefined { - return vscode.workspace.getConfiguration("http").get("proxy"); + return vscode.workspace.getConfiguration("http").get("proxy"); } diff --git a/src/utils/ConfigUtils.ts b/src/utils/ConfigUtils.ts index 698ac2f..ab38915 100644 --- a/src/utils/ConfigUtils.ts +++ b/src/utils/ConfigUtils.ts @@ -7,156 +7,160 @@ * Copyright (c) 2022 ccagml . All rights reserved. */ - - import { workspace, WorkspaceConfiguration, commands } from "vscode"; import { DescriptionConfiguration, Endpoint, IProblem, SortingStrategy } from "../model/Model"; // vscode的配置 export function getVsCodeConfig(): WorkspaceConfiguration { - return workspace.getConfiguration("leetcode-problem-rating"); + return workspace.getConfiguration("leetcode-problem-rating"); } // 隐藏解决题目 export function isHideSolvedProblem(): boolean { - return getVsCodeConfig().get("hideSolved", false); + return getVsCodeConfig().get("hideSolved", false); } // 隐藏分数 export function isHideScoreProblem(problem: IProblem, user_score: number): boolean { - const config_value: string = getVsCodeConfig().get("hideScore", "None"); - const min_v = getPickOneByRankRangeMin(); - const max_v = getPickOneByRankRangeMax(); - const p_score = problem?.scoreData?.Rating || 0; - const u_score = user_score > 0 ? user_score : 1500; - switch (config_value) { - case "Score": - if ((problem?.scoreData?.Rating || 0) > 0) { - return true; - } - break; - case "NoScore": - if ((problem?.scoreData?.Rating || 0) == 0) { - return true; - } - break; - case "ScoreRange": - if (p_score < u_score + min_v) { - return true; - } - if (p_score > u_score + max_v) { - return true; - } - break; - default: - break; - } - return false; + const config_value: string = getVsCodeConfig().get("hideScore", "None"); + const min_v = getPickOneByRankRangeMin(); + const max_v = getPickOneByRankRangeMax(); + const p_score = problem?.scoreData?.Rating || 0; + const u_score = user_score > 0 ? user_score : 1500; + switch (config_value) { + case "Score": + if ((problem?.scoreData?.Rating || 0) > 0) { + return true; + } + break; + case "NoScore": + if ((problem?.scoreData?.Rating || 0) == 0) { + return true; + } + break; + case "ScoreRange": + if (p_score < u_score + min_v) { + return true; + } + if (p_score > u_score + max_v) { + return true; + } + break; + default: + break; + } + return false; } // 随机题目最小分数 export function getPickOneByRankRangeMin(): number { - return getVsCodeConfig().get("pickOneByRankRangeMin") || 50; + return getVsCodeConfig().get("pickOneByRankRangeMin") || 50; } // 随机题目最大分数 export function getPickOneByRankRangeMax(): number { - return getVsCodeConfig().get("pickOneByRankRangeMax") || 150; + return getVsCodeConfig().get("pickOneByRankRangeMax") || 150; } // 工作目录 export function getWorkspaceFolder(): string { - return getVsCodeConfig().get("workspaceFolder", ""); + return getVsCodeConfig().get("workspaceFolder", ""); } // 快捷操作 export function getEditorShortcuts(): string[] { - return getVsCodeConfig().get("editor.shortcuts", ["submit", "case", "allcase", "test", "solution"]); + return getVsCodeConfig().get("editor.shortcuts", ["submit", "case", "allcase", "test", "solution"]); } export function isStarShortcut(): boolean { - const shortcuts: string[] = getVsCodeConfig().get("editor.shortcuts", ["submit", "case", "allcase", "test", "solution"]); - return shortcuts.indexOf("star") >= 0; + const shortcuts: string[] = getVsCodeConfig().get("editor.shortcuts", [ + "submit", + "case", + "allcase", + "test", + "solution", + ]); + return shortcuts.indexOf("star") >= 0; } export function isUseEndpointTranslation(): boolean { - return getVsCodeConfig().get("useEndpointTranslation", true); + return getVsCodeConfig().get("useEndpointTranslation", true); } // 状态栏状态设置 export function enableStatusBar(): boolean { - return getVsCodeConfig().get("enableStatusBar", true); + return getVsCodeConfig().get("enableStatusBar", true); } // 展示方式 export function getDescriptionConfiguration(): IDescriptionConfiguration { - const setting: string = getVsCodeConfig().get("showDescription", DescriptionConfiguration.InWebView); - const config: IDescriptionConfiguration = { - showInComment: false, - showInWebview: true, - }; - switch (setting) { - case DescriptionConfiguration.Both: - config.showInComment = true; - config.showInWebview = true; - break; - case DescriptionConfiguration.None: - config.showInComment = false; - config.showInWebview = false; - break; - case DescriptionConfiguration.InFileComment: - config.showInComment = true; - config.showInWebview = false; - break; - case DescriptionConfiguration.InWebView: - config.showInComment = false; - config.showInWebview = true; - break; - } - - // To be compatible with the deprecated setting: - if (getVsCodeConfig().get("showCommentDescription")) { - config.showInComment = true; - } - - return config; + const setting: string = getVsCodeConfig().get("showDescription", DescriptionConfiguration.InWebView); + const config: IDescriptionConfiguration = { + showInComment: false, + showInWebview: true, + }; + switch (setting) { + case DescriptionConfiguration.Both: + config.showInComment = true; + config.showInWebview = true; + break; + case DescriptionConfiguration.None: + config.showInComment = false; + config.showInWebview = false; + break; + case DescriptionConfiguration.InFileComment: + config.showInComment = true; + config.showInWebview = false; + break; + case DescriptionConfiguration.InWebView: + config.showInComment = false; + config.showInWebview = true; + break; + } + + // To be compatible with the deprecated setting: + if (getVsCodeConfig().get("showCommentDescription")) { + config.showInComment = true; + } + + return config; } export interface IDescriptionConfiguration { - showInComment: boolean; - showInWebview: boolean; + showInComment: boolean; + showInWebview: boolean; } export function enableSideMode(): boolean { - return getVsCodeConfig().get("enableSideMode", true); + return getVsCodeConfig().get("enableSideMode", true); } export function getNodePath() { - return getVsCodeConfig().get("nodePath", "node" /* default value */); + return getVsCodeConfig().get("nodePath", "node" /* default value */); } export function isShowLocked() { - return !!getVsCodeConfig().get("showLocked"); + return !!getVsCodeConfig().get("showLocked"); } export function isUseVscodeNode() { - return getVsCodeConfig().get("useVscodeNode") === true; + return getVsCodeConfig().get("useVscodeNode") === true; } export function isUseWsl() { - return getVsCodeConfig().get("useWsl") === true; + return getVsCodeConfig().get("useWsl") === true; } export function getSortingStrategy(): SortingStrategy { - return getVsCodeConfig().get("problems.sortStrategy", SortingStrategy.None); + return getVsCodeConfig().get("problems.sortStrategy", SortingStrategy.None); } export async function updateSortingStrategy(value: string, flag: boolean) { - await getVsCodeConfig().update("problems.sortStrategy", value, flag); + await getVsCodeConfig().update("problems.sortStrategy", value, flag); } export function getLeetCodeEndpoint(): string { - return getVsCodeConfig().get("endpoint", Endpoint.LeetCodeCN); + return getVsCodeConfig().get("endpoint", Endpoint.LeetCodeCN); } export async function openSettingsEditor(query?: string): Promise { - await commands.executeCommand("workbench.action.openSettings", query); + await commands.executeCommand("workbench.action.openSettings", query); } diff --git a/src/utils/OutputUtils.ts b/src/utils/OutputUtils.ts index d340978..f957381 100644 --- a/src/utils/OutputUtils.ts +++ b/src/utils/OutputUtils.ts @@ -7,92 +7,110 @@ * Copyright (c) 2022 ccagml . All rights reserved. */ - import * as vscode from "vscode"; import { DialogOptions, DialogType } from "../model/Model"; import { getLeetCodeEndpoint, getVsCodeConfig } from "./ConfigUtils"; export async function openUrl(url: string): Promise { - vscode.commands.executeCommand("vscode.open", vscode.Uri.parse(url)); + vscode.commands.executeCommand("vscode.open", vscode.Uri.parse(url)); } -export async function promptHintMessage(config: string, message: string, choiceConfirm: string, onConfirm: () => Promise): Promise { - if (getVsCodeConfig().get(config)) { - const choiceNoShowAgain: string = "Don't show again"; - const choice: string | undefined = await vscode.window.showInformationMessage( - message, choiceConfirm, choiceNoShowAgain, - ); - if (choice === choiceConfirm) { - await onConfirm(); - } else if (choice === choiceNoShowAgain) { - await getVsCodeConfig().update(config, false, true /* UserSetting */); - } +export async function promptHintMessage( + config: string, + message: string, + choiceConfirm: string, + onConfirm: () => Promise +): Promise { + if (getVsCodeConfig().get(config)) { + const choiceNoShowAgain: string = "Don't show again"; + const choice: string | undefined = await vscode.window.showInformationMessage( + message, + choiceConfirm, + choiceNoShowAgain + ); + if (choice === choiceConfirm) { + await onConfirm(); + } else if (choice === choiceNoShowAgain) { + await getVsCodeConfig().update(config, false, true /* UserSetting */); } + } } - export async function promptForSignIn(): Promise { - const choice: vscode.MessageItem | undefined = await vscode.window.showInformationMessage( - "Please sign in to LeetCode.", - DialogOptions.yes, - DialogOptions.no, - DialogOptions.singUp, - ); - switch (choice) { - case DialogOptions.yes: - await vscode.commands.executeCommand("leetcode.signin"); - break; - case DialogOptions.singUp: - if (getLeetCodeEndpoint()) { - openUrl("https://leetcode.cn"); - } else { - openUrl("https://leetcode.com"); - } - break; - default: - break; - } + const choice: vscode.MessageItem | undefined = await vscode.window.showInformationMessage( + "Please sign in to LeetCode.", + DialogOptions.yes, + DialogOptions.no, + DialogOptions.singUp + ); + switch (choice) { + case DialogOptions.yes: + await vscode.commands.executeCommand("leetcode.signin"); + break; + case DialogOptions.singUp: + if (getLeetCodeEndpoint()) { + openUrl("https://leetcode.cn"); + } else { + openUrl("https://leetcode.com"); + } + break; + default: + break; + } } export async function promptForOpenOutputChannel(message: string, type: DialogType): Promise { - let result: vscode.MessageItem | undefined; - switch (type) { - case DialogType.info: - result = await vscode.window.showInformationMessage(message, DialogOptions.open, DialogOptions.no); - break; - case DialogType.warning: - result = await vscode.window.showWarningMessage(message, DialogOptions.open, DialogOptions.no); - break; - case DialogType.error: - result = await vscode.window.showErrorMessage(message, DialogOptions.open, DialogOptions.no); - break; - default: - break; - } + let result: vscode.MessageItem | undefined; + switch (type) { + case DialogType.info: + result = await vscode.window.showInformationMessage(message, DialogOptions.open, DialogOptions.no); + break; + case DialogType.warning: + result = await vscode.window.showWarningMessage(message, DialogOptions.open, DialogOptions.no); + break; + case DialogType.error: + result = await vscode.window.showErrorMessage(message, DialogOptions.open, DialogOptions.no); + break; + default: + break; + } - if (result === DialogOptions.open) { - logOutput.show(); - } + if (result === DialogOptions.open) { + logOutput.show(); + } } class LogOutput implements vscode.Disposable { - private readonly channel: vscode.OutputChannel = vscode.window.createOutputChannel("LeetCodeProblemRating"); + private readonly channel: vscode.OutputChannel = vscode.window.createOutputChannel("LeetCodeProblemRating"); - public appendLine(message: string): void { - this.channel.appendLine(message); - } + private LCPTCTX = {}; + public appendLine(message: string): void { + this.channel.appendLine(message); + } - public append(message: string): void { - this.channel.append(message); - } + public append(message: string): void { + this.channel.append(message); + } - public show(): void { - this.channel.show(); - } + public show(): void { + this.channel.show(); + } - public dispose(): void { - this.channel.dispose(); - } + public dispose(): void { + this.channel.dispose(); + } + + public setLCPTCTX(k, v) { + this.LCPTCTX[k] = v; + } + + public getLCPTCTX(k) { + return this.LCPTCTX[k]; + } + + public getLCPTCTXAll() { + return this.LCPTCTX; + } } export const logOutput: LogOutput = new LogOutput(); diff --git a/src/utils/SystemUtils.ts b/src/utils/SystemUtils.ts index 419ab81..962088d 100644 --- a/src/utils/SystemUtils.ts +++ b/src/utils/SystemUtils.ts @@ -7,7 +7,6 @@ * Copyright (c) 2022 ccagml . All rights reserved. */ - import * as fse from "fs-extra"; import * as _ from "lodash"; import * as path from "path"; @@ -16,56 +15,58 @@ import { executeCommand } from "./CliUtils"; import { isUseVscodeNode, isUseWsl } from "./ConfigUtils"; export function isWindows(): boolean { - return process.platform === "win32"; + return process.platform === "win32"; } // 用wsl命令的时候,好像没办法用vscode的node // 相当于使用fork,而不是之前的 spawn(node xxx export function useVscodeNode(): boolean { - return !useWsl() && isUseVscodeNode(); + return !useWsl() && isUseVscodeNode(); } export function useWsl(): boolean { - return isWindows() && isUseWsl(); + return isWindows() && isUseWsl(); } export async function toWslPath(path: string): Promise { - return (await executeCommand("wsl", ["wslpath", "-u", `"${path.replace(/\\/g, "/")}"`])).trim(); + return (await executeCommand("wsl", ["wslpath", "-u", `"${path.replace(/\\/g, "/")}"`])).trim(); } export async function toWinPath(path: string): Promise { - if (path.startsWith("\\mnt\\")) { - return (await executeCommand("wsl", ["wslpath", "-w", `"${path.replace(/\\/g, "/").substr(0, 6)}"`])).trim() + path.substr(7); - } - return (await executeCommand("wsl", ["wslpath", "-w", "/"])).trim() + path; + if (path.startsWith("\\mnt\\")) { + return ( + (await executeCommand("wsl", ["wslpath", "-w", `"${path.replace(/\\/g, "/").substr(0, 6)}"`])).trim() + + path.substr(7) + ); + } + return (await executeCommand("wsl", ["wslpath", "-w", "/"])).trim() + path; } - export function genFileExt(language: string): string { - const ext: string | undefined = langExt.get(language); - if (!ext) { - throw new Error(`The language "${language}" is not supported.`); - } - return ext; + const ext: string | undefined = langExt.get(language); + if (!ext) { + throw new Error(`The language "${language}" is not supported.`); + } + return ext; } export function genFileName(node: IProblem, language: string): string { - const slug: string = _.kebabCase(node.name); - const ext: string = genFileExt(language); - return `${node.id}.${slug}.${ext}`; + const slug: string = _.kebabCase(node.name); + const ext: string = genFileExt(language); + return `${node.id}.${slug}.${ext}`; } export async function getNodeIdFromFile(fsPath: string): Promise { - const fileContent: string = await fse.readFile(fsPath, "utf8"); - let id: string = ""; - const matchResults: RegExpMatchArray | null = fileContent.match(/@lc.+id=(.+?) /); - if (matchResults && matchResults.length === 2) { - id = matchResults[1]; - } - // Try to get id from file name if getting from comments failed - if (!id) { - id = path.basename(fsPath).split(".")[0]; - } + const fileContent: string = await fse.readFile(fsPath, "utf8"); + let id: string = ""; + const matchResults: RegExpMatchArray | null = fileContent.match(/@lc.+id=(.+?) /); + if (matchResults && matchResults.length === 2) { + id = matchResults[1]; + } + // Try to get id from file name if getting from comments failed + if (!id) { + id = path.basename(fsPath).split(".")[0]; + } - return id; + return id; }