From 281240e80a162a1380e5cf42a6dbaf152f2f2a2f Mon Sep 17 00:00:00 2001 From: ccagml Date: Wed, 16 Nov 2022 15:25:38 +0800 Subject: [PATCH 01/26] format --- .eslintrc.js | 145 +- CHANGELOG.md | 64 +- README.md | 65 +- package-lock.json | 231 +- package.json | 5 +- resources/bin/leetcode | 2 +- src/childProcessCall/cli.ts | 42 +- src/childProcessCall/commands/cache.ts | 27 +- src/childProcessCall/commands/config.ts | 12 +- src/childProcessCall/commands/list.ts | 48 +- src/childProcessCall/commands/plugin.ts | 58 +- src/childProcessCall/commands/query.ts | 140 +- src/childProcessCall/commands/session.ts | 8 +- src/childProcessCall/commands/show.ts | 169 +- src/childProcessCall/commands/star.ts | 39 +- src/childProcessCall/commands/stat.ts | 6 +- src/childProcessCall/commands/submission.ts | 12 +- src/childProcessCall/commands/submit.ts | 89 +- src/childProcessCall/commands/test.ts | 131 +- src/childProcessCall/commands/user.ts | 168 +- src/childProcessCall/config.ts | 165 +- src/childProcessCall/core.ts | 101 +- src/childProcessCall/helper.ts | 190 +- src/childProcessCall/log.ts | 42 +- src/childProcessCall/my_plugin_base.ts | 37 +- src/childProcessCall/plugins/cache.ts | 218 +- src/childProcessCall/plugins/leetcode.cn.ts | 146 +- src/childProcessCall/plugins/leetcode.ts | 458 +- src/childProcessCall/plugins/retry.ts | 41 +- .../plugins/solution.discuss.ts | 94 +- src/childProcessCall/queue.ts | 21 +- src/childProcessCall/session.ts | 28 +- src/childProcessCall/storageUtils.ts | 141 +- src/controller/EventController.ts | 12 +- src/controller/FileButtonController.ts | 50 +- src/controller/LoginController.ts | 352 +- src/controller/MainController.ts | 37 +- src/controller/TreeViewController.ts | 3020 +++-- src/dao/choiceDao.ts | 2403 +--- src/dao/scoreDao.ts | 41 +- src/dao/tagsDao.ts | 10054 +++++++++++----- src/extension.ts | 155 +- src/model/Model.ts | 360 +- src/model/NodeModel.ts | 268 +- src/service/BaseWebviewService.ts | 138 +- src/service/EventService.ts | 53 +- src/service/ExecuteService.ts | 649 +- src/service/FileButtonService.ts | 205 +- src/service/MarkdownService.ts | 335 +- src/service/PreviewService.ts | 303 +- src/service/SolutionService.ts | 121 +- src/service/StatusBarService.ts | 242 +- src/service/SubmissionService.ts | 113 +- src/service/TreeDataService.ts | 322 +- src/service/TreeItemDecorationService.ts | 138 +- src/utils/CliUtils.ts | 161 +- src/utils/ConfigUtils.ts | 190 +- src/utils/OutputUtils.ts | 151 +- src/utils/SystemUtils.ts | 71 +- 59 files changed, 13389 insertions(+), 9698 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 991aab5..8571aab 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,80 +1,77 @@ 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"], + }, + // 如果有 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/CHANGELOG.md b/CHANGELOG.md index d2ca2ce..2b2ffb0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,114 +1,152 @@ ## 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..1773069 100644 --- a/README.md +++ b/README.md @@ -11,30 +11,36 @@

# 概要设计 + - 在 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) +![search](https://www.ccagml.com/wp-content/uploads/2022/10/search.gif) ## ❗️ 注意 ❗️- 无法登录 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 +78,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/package-lock.json b/package-lock.json index 6cdb985..4c850f1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "vscode-leetcode-problem-rating", - "version": "1.1.9", + "version": "2.0.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "vscode-leetcode-problem-rating", - "version": "1.1.9", + "version": "2.0.0", "license": "MIT", "dependencies": { "ansi-styles": "3.2.1", @@ -33,11 +33,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" @@ -307,14 +308,14 @@ } }, "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": { @@ -333,6 +334,110 @@ } } }, + "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": { + "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.43.0", + "@typescript-eslint/visitor-keys": "5.43.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": { + "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" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": { + "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.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" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": { + "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.43.0", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/parser/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/parser/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/scope-manager": { "version": "5.42.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.42.1.tgz", @@ -2478,6 +2583,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", @@ -3026,9 +3146,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", @@ -3484,15 +3604,76 @@ } }, "@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" + }, + "dependencies": { + "@typescript-eslint/scope-manager": { + "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.43.0", + "@typescript-eslint/visitor-keys": "5.43.0" + } + }, + "@typescript-eslint/types": { + "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.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.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" + } + }, + "@typescript-eslint/visitor-keys": { + "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.43.0", + "eslint-visitor-keys": "^3.3.0" + } + }, + "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/scope-manager": { @@ -5080,6 +5261,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", @@ -5459,9 +5646,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": { diff --git a/package.json b/package.json index ceb8cdb..6c34a45 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/resources/bin/leetcode b/resources/bin/leetcode index eab3991..f19b706 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/cli"); diff --git a/src/childProcessCall/cli.ts b/src/childProcessCall/cli.ts index 5cba554..dd3afa5 100644 --- a/src/childProcessCall/cli.ts +++ b/src/childProcessCall/cli.ts @@ -1,4 +1,3 @@ - /* * Filename: https://github.com/ccagml/vscode-leetcode-problem-rating/src/childProcessCall/cli.ts * Path: https://github.com/ccagml/vscode-leetcode-problem-rating @@ -9,33 +8,32 @@ */ // 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)); + 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 index f8fb0ec..e2a0be6 100644 --- a/src/childProcessCall/commands/cache.ts +++ b/src/childProcessCall/commands/cache.ts @@ -7,43 +7,40 @@ * 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() { - } + constructor() {} process_argv = function (argv) { - let argv_config = helper.base_argv().option('d', { - alias: 'delete', - type: 'boolean', - describe: 'Delete cache by keyword', - default: false + 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); - }); + 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) { diff --git a/src/childProcessCall/commands/config.ts b/src/childProcessCall/commands/config.ts index 9936333..6f2604f 100644 --- a/src/childProcessCall/commands/config.ts +++ b/src/childProcessCall/commands/config.ts @@ -7,11 +7,9 @@ * 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"; @@ -19,9 +17,7 @@ // import { helper } from "../helper"; class ConfigCommand { - constructor() { - - } + constructor() {} // process_argv(argv) { // let argv_config = helper.base_argv().option('a', { @@ -51,7 +47,6 @@ class ConfigCommand { // return argv_config.get_result(); // } - // prettyConfig(cfg) { // return JSON.stringify(cfg, null, 2); // } @@ -73,7 +68,6 @@ class ConfigCommand { // if (argv.key.length === 0) // return log.info(this.prettyConfig(this.loadConfig(argv.all))); - // const v = nconf.get(argv.key); // // delete @@ -99,8 +93,4 @@ class ConfigCommand { // }; } - - - export const configCommand: ConfigCommand = new ConfigCommand(); - diff --git a/src/childProcessCall/commands/list.ts b/src/childProcessCall/commands/list.ts index 4548b22..9bb0510 100644 --- a/src/childProcessCall/commands/list.ts +++ b/src/childProcessCall/commands/list.ts @@ -1,4 +1,3 @@ - /* * Filename: https://github.com/ccagml/vscode-leetcode-problem-rating/src/childProcessCall/commands/list.ts * Path: https://github.com/ccagml/vscode-leetcode-problem-rating @@ -8,42 +7,41 @@ * 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() { - - } + constructor() {} process_argv(argv) { - let argv_config = helper.base_argv().option('q', corePlugin.filters.query) - .option('s', { - alias: 'stat', - type: 'boolean', + 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' + describe: "Show statistics of listed questions", }) - .option('t', corePlugin.filters.tag) - .option('x', { - alias: 'extra', - type: 'boolean', + .option("t", corePlugin.filters.tag) + .option("x", { + alias: "extra", + type: "boolean", default: false, - describe: 'Show extra details: category, companies, tags.' + describe: "Show extra details: category, companies, tags.", }) - .option('T', { - alias: 'dontTranslate', - type: 'boolean', + .option("T", { + alias: "dontTranslate", + type: "boolean", default: false, - describe: 'Set to true to disable endpoint\'s translation', + describe: "Set to true to disable endpoint's translation", }) - .positional('keyword', { - type: 'string', - default: '', - describe: 'Filter questions by keyword' + .positional("keyword", { + type: "string", + default: "", + describe: "Filter questions by keyword", }); argv_config.process_argv(argv); @@ -56,7 +54,7 @@ class ListCommand { corePlugin.filterProblems(argv, function (e, problems) { if (e) return log.info(e); let new_objcet: Array = []; - problems.forEach(element => { + problems.forEach((element) => { let temp_ele: any = {}; for (const key in element) { if (key != "link") { @@ -67,7 +65,7 @@ class ListCommand { }); 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 index 7f187e4..87cdbc6 100644 --- a/src/childProcessCall/commands/plugin.ts +++ b/src/childProcessCall/commands/plugin.ts @@ -7,40 +7,41 @@ * 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() { - - } + 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: '' - }); + 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); @@ -65,10 +66,10 @@ class PluginCommand { // } if (name) { - all_plugin = all_plugin.filter(x => x.name === name); - }; + all_plugin = all_plugin.filter((x) => x.name === name); + } if (all_plugin.length === 0) { - return log.fatal('Plugin not found!'); + return log.fatal("Plugin not found!"); } const p = all_plugin[0]; @@ -88,5 +89,4 @@ class PluginCommand { }; } - export const pluginCommand: PluginCommand = new PluginCommand(); diff --git a/src/childProcessCall/commands/query.ts b/src/childProcessCall/commands/query.ts index 173e7e8..9487b5d 100644 --- a/src/childProcessCall/commands/query.ts +++ b/src/childProcessCall/commands/query.ts @@ -7,83 +7,85 @@ * 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(); - }; + 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)); - }); + 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 index e1955e6..fb50971 100644 --- a/src/childProcessCall/commands/session.ts +++ b/src/childProcessCall/commands/session.ts @@ -7,18 +7,13 @@ * 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() { - - } + constructor() {} // printSessions(e, sessions) { // if (e) return log.info(e); @@ -82,5 +77,4 @@ class SessionCommand { // }; } - export const sessionCommand: SessionCommand = new SessionCommand(); diff --git a/src/childProcessCall/commands/show.ts b/src/childProcessCall/commands/show.ts index c09caf3..6d2b736 100644 --- a/src/childProcessCall/commands/show.ts +++ b/src/childProcessCall/commands/show.ts @@ -7,10 +7,8 @@ * Copyright (c) 2022 ccagml . All rights reserved. */ - -let util = require('util'); -let childProcess = require('child_process'); - +let util = require("util"); +let childProcess = require("child_process"); import { helper } from "../helper"; import { storageUtils } from "../storageUtils"; @@ -21,70 +19,78 @@ import { corePlugin } from "../core"; import { session } from "../session"; class ShowCommand { - constructor() { - - } - + 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', + 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: 'Show extra question details in source code' - }).option('T', { - alias: 'dontTranslate', - type: 'boolean', + 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: 'Set to true to disable endpoint\'s translation', - }).positional('keyword', { - type: 'string', - default: '', - describe: 'Show question by name or id' + 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 path = require("path"); const params = [ storageUtils.fmt(config.file.show, problem), - '', - helper.langToExt(opts.lang) + "", + 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; + const name = path.join( + opts.outdir, + params.join(".").replace(/\.+/g, ".") + ); + if (!storageUtils.exist(name)) return name; params[1] = i; } } @@ -93,27 +99,27 @@ class ShowCommand { const taglist = [problem.category] .concat(problem.companies || []) .concat(problem.tags || []) - .map(x => helper.badge(x)) - .join(' '); + .map((x) => helper.badge(x)) + .join(" "); const langlist = problem.templates - .map(x => helper.badge(x.value)) + .map((x) => helper.badge(x.value)) .sort() - .join(' '); + .join(" "); let code; const needcode = argv.gen || argv.codeonly; if (needcode) { - const template = problem.templates.find(x => x.value === argv.lang); + const template = problem.templates.find((x) => x.value === argv.lang); if (!template) { log.info('Not supported language "' + argv.lang + '"'); - log.warn('Supported languages: ' + langlist); + log.warn("Supported languages: " + langlist); return; } const opts = { lang: argv.lang, code: template.defaultCode, - tpl: argv.extra ? 'detailed' : 'codeonly' + tpl: argv.extra ? "detailed" : "codeonly", }; code = corePlugin.exportProblem(problem, opts); } @@ -127,7 +133,7 @@ class ShowCommand { if (argv.editor !== undefined) { childProcess.spawn(argv.editor || config.code.editor, [filename], { // in case your editor of choice is vim or emacs - stdio: 'inherit' + stdio: "inherit", }); } } else { @@ -142,31 +148,28 @@ class ShowCommand { log.info(problem.link); if (argv.extra) { log.info(); - log.info('Tags: ' + taglist); + log.info("Tags: " + taglist); log.info(); - log.info('Langs: ' + langlist); + 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}`); + 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}`); + if (filename) log.info(`* Source Code: ${filename}`); log.info(); log.info(problem.desc); @@ -177,16 +180,18 @@ class ShowCommand { 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); - }); + 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 index 198cc45..f9f97ba 100644 --- a/src/childProcessCall/commands/star.ts +++ b/src/childProcessCall/commands/star.ts @@ -1,4 +1,3 @@ - /* * Filename: https://github.com/ccagml/vscode-leetcode-problem-rating/src/childProcessCall/commands/star.ts * Path: https://github.com/ccagml/vscode-leetcode-problem-rating @@ -8,31 +7,29 @@ * 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() { - - } + 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: '' + 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(); @@ -46,13 +43,15 @@ class StarCommand { 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'}`); + 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 index c207724..5e0b7e1 100644 --- a/src/childProcessCall/commands/stat.ts +++ b/src/childProcessCall/commands/stat.ts @@ -7,7 +7,6 @@ * Copyright (c) 2022 ccagml . All rights reserved. */ - // let moment_out = require('moment'); // let underscore = require('underscore'); @@ -17,9 +16,7 @@ // import { session } from "../session"; class StatCommand { - constructor() { - - } + constructor() {} // process_argv(argv) { // let argv_config = helper.base_argv().option('c', { @@ -217,4 +214,3 @@ class StatCommand { } export const statCommand: StatCommand = new StatCommand(); - diff --git a/src/childProcessCall/commands/submission.ts b/src/childProcessCall/commands/submission.ts index f0ff5ef..614c23c 100644 --- a/src/childProcessCall/commands/submission.ts +++ b/src/childProcessCall/commands/submission.ts @@ -7,14 +7,10 @@ * Copyright (c) 2022 ccagml . All rights reserved. */ - - // let path = require('path'); // let _ = require('underscore'); - - // import { helper } from "../helper"; // import { file } from "../file"; // import { config } from "../config"; @@ -23,11 +19,8 @@ // import { corePlugin } from "../core"; // import { session } from "../session"; - class SubMission { - constructor() { - - } + constructor() {} // process_argv = function (argv) { // let argv_config = helper.base_argv().option('a', { @@ -70,7 +63,6 @@ class SubMission { // return argv_config.get_result(); // }; - // doTask(problem, queue, cb) { // let that = this; // const argv = queue.ctx.argv; @@ -161,6 +153,4 @@ class SubMission { // }; } - - export const subMissionCommand: SubMission = new SubMission(); diff --git a/src/childProcessCall/commands/submit.ts b/src/childProcessCall/commands/submit.ts index 76cc91a..564151c 100644 --- a/src/childProcessCall/commands/submit.ts +++ b/src/childProcessCall/commands/submit.ts @@ -7,11 +7,8 @@ * Copyright (c) 2022 ccagml . All rights reserved. */ - - -let util = require('util'); -let lodash = require('lodash'); - +let util = require("util"); +let lodash = require("lodash"); import { helper } from "../helper"; import { storageUtils } from "../storageUtils"; @@ -19,33 +16,27 @@ import { log } from "../log"; import { corePlugin } from "../core"; import { session } from "../session"; - - class SubmitCommand { - constructor() { - - } - + constructor() {} process_argv(argv) { - let argv_config = helper.base_argv().positional('filename', { - type: 'string', - describe: 'Code file to submit', - default: '' + 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 v = actual[k] || ""; const lines = Array.isArray(v) ? v : [v]; for (let line of lines) { - if (k !== 'state') { + if (k !== "state") { if (!log_obj.hasOwnProperty(lodash.startCase(k))) { log_obj[lodash.startCase(k)] = [line]; } else { @@ -66,7 +57,7 @@ class SubmitCommand { handler(argv) { session.argv = argv; if (!storageUtils.exist(argv.filename)) - return log.fatal('File ' + argv.filename + ' not exist!'); + return log.fatal("File " + argv.filename + " not exist!"); const meta = storageUtils.meta(argv.filename); let that = this; @@ -91,41 +82,57 @@ class SubmitCommand { 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); + 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); + 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.'); + 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.'); + 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); + 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') }); + 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 index 324c634..50a93da 100644 --- a/src/childProcessCall/commands/test.ts +++ b/src/childProcessCall/commands/test.ts @@ -7,11 +7,8 @@ * Copyright (c) 2022 ccagml . All rights reserved. */ - - -let _ = require('underscore'); -let lodash = require('lodash'); - +let _ = require("underscore"); +let lodash = require("lodash"); import { helper } from "../helper"; import { storageUtils } from "../storageUtils"; @@ -19,36 +16,34 @@ import { log } from "../log"; import { corePlugin } from "../core"; import { session } from "../session"; - class TestCommand { - constructor() { - - } - + 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' + let argv_config = helper + .base_argv() + .option("i", { + alias: "interactive", + type: "boolean", + default: false, + describe: "Provide test case interactively", }) - .option('a', { - alias: 'allcase', - type: 'boolean', + .option("t", { + alias: "testcase", + type: "string", + default: "", + describe: "Provide test case", + }) + .option("a", { + alias: "allcase", + type: "boolean", default: false, - describe: 'Provide all test case' + describe: "Provide all test case", }) - .positional('filename', { - type: 'string', - default: '', - describe: 'Code file to test' + .positional("filename", { + type: "string", + default: "", + describe: "Code file to test", }); argv_config.process_argv(argv); @@ -56,19 +51,18 @@ class TestCommand { 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; + 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') { + 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]; @@ -84,7 +78,7 @@ class TestCommand { runTest(argv) { let that = this; if (!storageUtils.exist(argv.filename)) - return log.fatal('File ' + argv.filename + ' not exist!'); + return log.fatal("File " + argv.filename + " not exist!"); const meta = storageUtils.meta(argv.filename); @@ -92,23 +86,38 @@ class TestCommand { // 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 (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!'] })); + 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'); + 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()); + 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'); + 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 = ""; @@ -160,7 +169,6 @@ class TestCommand { temp_collect = ""; } } - } if (temp_test.length < 1) { @@ -171,7 +179,13 @@ class TestCommand { } if (!problem.testcase) - return log.info(JSON.stringify({ messages: ["error"], code: [-3], error: ['missing testcase?'] })); + return log.info( + JSON.stringify({ + messages: ["error"], + code: [-3], + error: ["missing testcase?"], + }) + ); problem.file = argv.filename; problem.lang = meta.lang; @@ -179,8 +193,7 @@ class TestCommand { corePlugin.testProblem(problem, function (e, results) { if (e) return log.info(JSON.stringify(e)); - - results = _.sortBy(results, x => x.type); + results = _.sortBy(results, (x) => x.type); let log_obj: any = {}; log_obj.messages = []; @@ -191,12 +204,12 @@ class TestCommand { log_obj.system_message.sub_type = "test"; log_obj.system_message.accepted = false; - if (results[0].state === 'Accepted') { - results[0].state = 'Finished'; + 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); + 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; @@ -204,11 +217,13 @@ class TestCommand { 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); + 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)); }); }); @@ -217,8 +232,7 @@ class TestCommand { handler(argv) { let that = this; session.argv = argv; - if (!argv.i) - return that.runTest(argv); + if (!argv.i) return that.runTest(argv); helper.readStdin(function (e, data) { if (e) return log.info(e); @@ -226,8 +240,7 @@ class TestCommand { 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 index 71a5739..b70e870 100644 --- a/src/childProcessCall/commands/user.ts +++ b/src/childProcessCall/commands/user.ts @@ -7,48 +7,47 @@ * Copyright (c) 2022 ccagml . All rights reserved. */ - -let prompt_out = require('prompt'); +let prompt_out = require("prompt"); import { helper } from "../helper"; import { log } from "../log"; import { corePlugin } from "../core"; import { session } from "../session"; class UserCommand { - constructor() { - - } + 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', + 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' + describe: "cookieLogin", }) - .option('g', { - alias: 'github', - type: 'boolean', + .option("g", { + alias: "github", + type: "boolean", default: false, - describe: 'githubLogin' + describe: "githubLogin", }) - .option('i', { - alias: 'linkedin', - type: 'boolean', + .option("i", { + alias: "linkedin", + type: "boolean", default: false, - describe: 'linkedinLogin' + describe: "linkedinLogin", }) - .option('L', { - alias: 'logout', - type: 'boolean', + .option("L", { + alias: "logout", + type: "boolean", default: false, - describe: 'Logout' + describe: "Logout", }); argv_config.process_argv(argv); @@ -56,92 +55,99 @@ class UserCommand { 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.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) { + prompt_out.get( + [ + { name: "login", required: true }, + { name: "pass", required: true, hidden: true }, + ], + function (e, user) { if (e) { - return log.info(JSON.stringify({ code: -2, msg: e.msg || e })); + return log.info(JSON.stringify({ code: -1, msg: e.msg || e })); } - log.info(JSON.stringify({ code: 100, user_name: user.name })); - }); - }); + + 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 })); + 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?' })); + 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 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.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 })); - }); - }); + 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.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 })); - }); - }); + 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?' })); + 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 index fcb4ebd..e2b4b68 100644 --- a/src/childProcessCall/config.ts +++ b/src/childProcessCall/config.ts @@ -7,8 +7,7 @@ * Copyright (c) 2022 ccagml . All rights reserved. */ - -let underscore = require('underscore'); +let underscore = require("underscore"); class Config { app; @@ -22,124 +21,124 @@ class Config { plugins; constructor() { this.sys = { - categories: [ - 'algorithms', - 'LCCI', - 'LCOF', - 'LCOF2' - ], + categories: ["algorithms", "LCCI", "LCOF", "LCOF2"], langs: [ - '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", ], urls: { // base urls - base: 'https://leetcode.com', - graphql: 'https://leetcode.com/graphql', - login: 'https://leetcode.com/accounts/login/', + 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', + 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', + 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', + 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: '', + 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 + retry: 2, }; this.code = { - editor: 'vim', - lang: 'cpp' + editor: "vim", + lang: "cpp", }; this.file = { - show: '${fid}.${slug}', - submission: '${fid}.${slug}.${sid}.${ac}' + show: "${fid}.${slug}", + submission: "${fid}.${slug}.${sid}.${ac}", }; this.color = { enable: true, - theme: 'default' + theme: "default", }; this.icon = { - theme: '' + theme: "", }; this.network = { concurrency: 10, - delay: 1 + delay: 1, }; this.plugins = {}; } - init() { - }; + 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/'; + 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/core.ts b/src/childProcessCall/core.ts index 2fb9aa9..4d0e1b9 100644 --- a/src/childProcessCall/core.ts +++ b/src/childProcessCall/core.ts @@ -7,11 +7,10 @@ * 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 { log } from "./log"; import { helper } from "./helper"; @@ -20,57 +19,56 @@ import { storageUtils } from "./storageUtils"; import { MyPluginBase } from "./my_plugin_base"; 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 { id = 99999999; - name = 'core'; + name = "core"; builtin = true; filters = { query: { - alias: 'query', - type: 'string', - default: '', + 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') + "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', + alias: "tag", + type: "array", default: [], - describe: 'Filter questions by tag' - } + 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) + ); }); } @@ -82,24 +80,30 @@ class CorePlugin extends MyPluginBase { this.getProblems(needTranslation, function (e, problems) { if (e) return cb(e); keyword = Number(keyword) || keyword; - const metaFid = storageUtils.exist(keyword) ? storageUtils.meta(keyword).id : NaN; + 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); } @@ -111,24 +115,24 @@ class CorePlugin extends MyPluginBase { // unify format before rendering - data.app = require('./config').app || 'leetcode'; + data.app = require("./config").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.code = (opts.code || data.code || "").replace(/\r\n/g, "\n"); data.comment = helper.langToCommentStyle(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 +166,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 +183,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/helper.ts b/src/childProcessCall/helper.ts index e9c9c07..da2df98 100644 --- a/src/childProcessCall/helper.ts +++ b/src/childProcessCall/helper.ts @@ -7,8 +7,7 @@ * Copyright (c) 2022 ccagml . All rights reserved. */ - -let ora = require('ora'); +let ora = require("ora"); import { storageUtils } from "./storageUtils"; @@ -39,36 +38,36 @@ import { storageUtils } from "./storageUtils"; // } 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' } + { 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 + user: "../user", + stat: "../stat", + plugins: "../../plugins", + problems: "problems", + translation: "translationConfig", + ranting_path: "../../rating", + problem: (p) => p.fid + "." + p.slug + "." + p.category, }; } @@ -101,107 +100,133 @@ class HELPER { prettyLevel(level) { switch (level.toLowerCase().trim()) { - case 'easy': return (level); - case 'medium': return (level); - case 'hard': return (level); - default: return level; + 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 ' '; + 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'; + 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'; - }; + 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'; - }; + const res = LANGS.find((x) => fullpath.endsWith(x.ext)); + return res ? res.lang : "unknown"; + } langToCommentStyle(lang) { - const res = LANGS.find(x => x.lang === 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 }; - }; + 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 ' : '')); + console.log( + "NOTE: to finish the input, press " + + (storageUtils.isWindows() ? " and " : "") + ); - stdin.on('readable', function () { + 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'); + if (storageUtils.isWindows() && data.toString() === "\x04\r\n") { + stdin.emit("end"); } else { bufs.push(data); } } }); - stdin.on('end', function () { + stdin.on("end", function () { cb(null, Buffer.concat(bufs).toString()); }); - stdin.on('error', cb); - }; + stdin.on("error", cb); + } getSetCookieValue(resp, key) { - const cookies = resp.headers['set-cookie']; + const cookies = resp.headers["set-cookie"]; if (!cookies) return null; for (let i = 0; i < cookies.length; ++i) { - const sections = cookies[i].split(';'); + const sections = cookies[i].split(";"); for (let j = 0; j < sections.length; ++j) { - const kv = sections[j].trim().split('='); + 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'); - }; + 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); - }; + s = " " + s + " "; + return s; + } base_argv() { let base = { @@ -257,10 +282,9 @@ class HELPER { let all_posi = 0; for (let index = 3; index < argv.length; index++) { let con = argv[index]; - if (con[0] == '-' && con[1] == '-') { + if (con[0] == "-" && con[1] == "-") { this.set_opt(con.substring(2)); - } - else if (con[0] == '-') { + } 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++; @@ -274,12 +298,10 @@ class HELPER { }, 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 index 37bea8d..2252412 100644 --- a/src/childProcessCall/log.ts +++ b/src/childProcessCall/log.ts @@ -7,58 +7,56 @@ * Copyright (c) 2022 ccagml . All rights reserved. */ - -let _ = require('underscore'); - +let _ = require("underscore"); class LOG { output = _.bind(console.log, console); level; levels = new Map([ - ['INFO', { value: 2 }], - ['WARN', { value: 3 }], - ['ERROR', { value: 4 }], + ["INFO", { value: 2 }], + ["WARN", { value: 3 }], + ["ERROR", { value: 4 }], ]); setLevel(name) { - this.level = this.levels.get(name) || this.levels.get('INFO'); - }; + this.level = this.levels.get(name) || this.levels.get("INFO"); + } fail(e) { - let msg = (e.msg || e); + let msg = e.msg || e; if (e.statusCode) { - msg += (' [code=' + e.statusCode + ']'); + msg += " [code=" + e.statusCode + "]"; } this.error(msg); - }; + } fatal(e) { this.error(e); process.exit(1); - }; + } init() { - this.setLevel('INFO'); - }; + this.setLevel("INFO"); + } info(...rest: any[]) { const args = rest; //Array.from(arguments); - let s = args.map(x => x.toString()).join(' '); + let s = args.map((x) => x.toString()).join(" "); this.output(s); - }; + } warn(...rest: any[]) { const args = rest; //Array.from(arguments); - args.unshift('[' + "warn" + ']'); + args.unshift("[" + "warn" + "]"); - let s = args.map(x => x.toString()).join(' '); + let s = args.map((x) => x.toString()).join(" "); this.output(s); - }; + } error(...rest: any[]) { const args = rest; //Array.from(arguments); - args.unshift('[' + "error" + ']'); + args.unshift("[" + "error" + "]"); - let s = args.map(x => x.toString()).join(' '); + 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 index 7e97349..1a0dd1a 100644 --- a/src/childProcessCall/my_plugin_base.ts +++ b/src/childProcessCall/my_plugin_base.ts @@ -7,8 +7,7 @@ * Copyright (c) 2022 ccagml . All rights reserved. */ - -let underscore = require('underscore'); +let underscore = require("underscore"); import { config as out_config } from "./config"; import { storageUtils } from "./storageUtils"; @@ -29,8 +28,7 @@ export class MyPluginBase { installed: Array = []; head; // 插件头 是core config; - constructor() { - } + constructor() {} public save() { const stats = storageUtils.getCache(helper.KEYS.plugins) || {}; @@ -39,17 +37,17 @@ export class MyPluginBase { 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; + head = head || require("./core").corePlugin; const stats = storageUtils.getCache(helper.KEYS.plugins) || {}; - let file_plugin: Array = storageUtils.listCodeDir('plugins'); + let file_plugin: Array = storageUtils.listCodeDir("plugins"); this.installed = []; for (let f of file_plugin) { const p = f.data; @@ -66,7 +64,7 @@ export class MyPluginBase { this.installed.push(p); } // 根据id大小排序, 大的前面 - this.installed = underscore.sortBy(this.installed, x => -x.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]; @@ -75,24 +73,24 @@ export class MyPluginBase { } } // 连成链表状 - this.plugins = this.installed.filter(x => x.enabled); + 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); @@ -122,47 +120,36 @@ export class MyPluginBase { } 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); @@ -195,6 +182,4 @@ export class MyPluginBase { } } - - export const myPluginBase: MyPluginBase = new MyPluginBase(); diff --git a/src/childProcessCall/plugins/cache.ts b/src/childProcessCall/plugins/cache.ts index e94fbf9..350217c 100644 --- a/src/childProcessCall/plugins/cache.ts +++ b/src/childProcessCall/plugins/cache.ts @@ -7,127 +7,125 @@ * Copyright (c) 2022 ccagml . All rights reserved. */ - import { MyPluginBase } from "../my_plugin_base"; -let underscore = require('underscore'); - +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(); + 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, + }); } + }; - 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;
-    };
+  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/leetcode.cn.ts b/src/childProcessCall/plugins/leetcode.cn.ts
index 1137db9..3c166a6 100644
--- a/src/childProcessCall/plugins/leetcode.cn.ts
+++ b/src/childProcessCall/plugins/leetcode.cn.ts
@@ -7,10 +7,9 @@
  * Copyright (c) 2022 ccagml . All rights reserved.
  */
 
-
 import { MyPluginBase } from "../my_plugin_base";
 
-let request = require('request');
+let request = require("request");
 
 import { config } from "../config";
 
@@ -18,14 +17,14 @@ import { session } from "../session";
 
 class LeetCodeCn extends MyPluginBase {
   id = 15;
-  name = 'leetcode.cn';
+  name = "leetcode.cn";
   builtin = true;
   constructor() {
     super();
   }
   init() {
     config.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/';
+    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/';
+    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);
+    opts.headers.Referer = config.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,34 +176,41 @@ 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) {
-      // console.log(error);
-      // console.log(info);
-      cb(error, body);
-    });
+    _request(
+      "https://zerotrac.github.io/leetcode_problem_rating/data.json",
+      function (error, _, body) {
+        // console.log(error);
+        // console.log(info);
+        cb(error, body);
+      }
+    );
   };
 
-
   getTestApi = (value, _) => {
     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, info, body) {
+        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';
+  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) {
@@ -222,8 +218,7 @@ function makeOpts(url) {
   opts.url = url;
   opts.headers = {};
 
-  if (session.isLogin())
-    signOpts(opts, session.getUser());
+  if (session.isLogin()) signOpts(opts, session.getUser());
   return opts;
 }
 
@@ -231,11 +226,10 @@ function checkError(e, resp, expectedStatus) {
   if (!e && resp && resp.statusCode !== expectedStatus) {
     const code = resp.statusCode;
 
-
     if (code === 403 || code === 401) {
       e = session.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/childProcessCall/plugins/leetcode.ts
index bfaa5d9..3853fa0 100644
--- a/src/childProcessCall/plugins/leetcode.ts
+++ b/src/childProcessCall/plugins/leetcode.ts
@@ -7,13 +7,11 @@
  * Copyright (c) 2022 ccagml . All rights reserved.
  */
 
+let util = require("util");
 
-
-let util = require('util');
-
-let underscore = require('underscore');
-let request = require('request');
-let prompt_out = require('prompt');
+let underscore = require("underscore");
+let request = require("request");
+let prompt_out = require("prompt");
 
 import { config } from "../config";
 import { helper } from "../helper";
@@ -25,28 +23,31 @@ import { Queue } from "../queue";
 
 class LeetCode extends MyPluginBase {
   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 (session.isLogin()) this.signOpts(opts, session.getUser());
     return opts;
-  };
+  }
 
   checkError(e, resp, expectedStatus) {
     if (!e && resp && resp.statusCode !== expectedStatus) {
@@ -55,15 +56,15 @@ class LeetCode extends MyPluginBase {
       if (code === 403 || code === 401) {
         e = session.errors.EXPIRED;
       } else {
-        e = { msg: 'http error', statusCode: code };
+        e = { msg: "http error", statusCode: code };
       }
     }
     return e;
-  };
+  }
 
   init() {
-    config.app = 'leetcode';
-  };
+    config.app = "leetcode";
+  }
 
   getProblems = (_, cb) => {
     let that = this;
@@ -73,24 +74,22 @@ class LeetCode extends MyPluginBase {
         if (e) {
           //
         } else {
-
           problems = problems.concat(_problems);
         }
         return cb(e);
       });
     };
 
-
     const q = new Queue(config.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(
+      config.sys.urls.problems.replace("$category", category)
+    );
 
     let that = this;
     request(opts, function (e, resp, body) {
@@ -99,9 +98,7 @@ class LeetCode extends MyPluginBase {
 
       const json = JSON.parse(body);
 
-
       if (json.user_name.length === 0) {
-
         return cb(session.errors.EXPIRED);
       }
 
@@ -109,17 +106,20 @@ class LeetCode extends MyPluginBase {
         .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: config.sys.urls.problem.replace(
+              "$slug",
+              p.stat.question__title_slug
+            ),
             locked: p.paid_only,
-            percent: p.stat.total_acs * 100 / p.stat.total_submitted,
+            percent: (p.stat.total_acs * 100) / p.stat.total_submitted,
             level: helper.levelToName(p.difficulty.level),
             starred: p.is_favor,
-            category: json.category_slug
+            category: json.category_slug,
           };
         });
 
@@ -128,9 +128,9 @@ class LeetCode extends MyPluginBase {
   };
 
   getProblem = (problem, needTranslation, cb) => {
-
     const user = session.getUser();
-    if (problem.locked && !user.paid) return cb('failed to load locked problem!');
+    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;
@@ -139,40 +139,41 @@ class LeetCode extends MyPluginBase {
     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,7 +186,7 @@ class LeetCode extends MyPluginBase {
     });
   };
   runCode = (opts, problem, cb) => {
-    opts.method = 'POST';
+    opts.method = "POST";
     opts.headers.Origin = config.sys.urls.base;
     opts.headers.Referer = problem.link;
     opts.json = true;
@@ -196,20 +197,16 @@ class LeetCode extends MyPluginBase {
       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 +221,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 = config.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 +247,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 +267,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,29 +282,32 @@ 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(
+      config.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);
+      const q = new Queue(
+        tasks,
+        { opts: opts, results: [] },
+        that.verifyResult
+      );
       q.run(null, function (e, ctx) {
         return cb(e, ctx.results);
       });
@@ -317,15 +315,20 @@ 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(
+      config.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 q = new Queue(tasks, { opts: opts, results: [] }, that.verifyResult);
+      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 +336,13 @@ 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(
+      config.sys.urls.submissions.replace("$slug", problem.slug)
+    );
+    opts.headers.Referer = config.sys.urls.problem.replace(
+      "$slug",
+      problem.slug
+    );
     let that = this;
     request(opts, function (e, resp, body) {
       e = that.checkError(e, resp, 200);
@@ -344,15 +351,18 @@ 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(
+      config.sys.urls.submission.replace("$id", submission.id)
+    );
     let that = this;
     request(opts, function (e, resp, body) {
       e = that.checkError(e, resp, 200);
@@ -368,9 +378,10 @@ class LeetCode extends MyPluginBase {
   };
 
   starProblem = (problem, starred, cb) => {
-
     const user = session.getUser();
-    const operationName = starred ? 'addQuestionToFavorite' : 'removeQuestionFromFavorite';
+    const operationName = starred
+      ? "addQuestionToFavorite"
+      : "removeQuestionFromFavorite";
     const opts = this.makeOpts(config.sys.urls.graphql);
     opts.headers.Origin = config.sys.urls.base;
     opts.headers.Referer = problem.link;
@@ -378,14 +389,12 @@ class LeetCode extends MyPluginBase {
     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, _) {
-
       e = that.checkError(e, resp, 200);
       if (e) return cb(e);
       return cb(null, starred);
@@ -393,13 +402,10 @@ class LeetCode extends MyPluginBase {
   };
 
   getFavorites = (cb) => {
-
     const opts = this.makeOpts(config.sys.urls.favorites);
 
-
     let that = this;
     request(opts, function (e, resp, body) {
-
       e = that.checkError(e, resp, 200);
       if (e) return cb(e);
 
@@ -416,19 +422,17 @@ class LeetCode extends MyPluginBase {
     opts.json = true;
     opts.body = {
       query: [
-        '{',
-        '  user {',
-        '    username',
-        '    isCurrentUserPremium',
-        '  }',
-        '}'
-      ].join('\n'),
-      variables: {}
+        "{",
+        "  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,17 +441,14 @@ class LeetCode extends MyPluginBase {
     });
   };
 
-
   runSession = (method, data, cb) => {
     const opts = this.makeOpts(config.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;
 
@@ -456,57 +457,56 @@ class LeetCode extends MyPluginBase {
   };
 
   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');
+    const isCN = config.app === "leetcode.cn";
+    const spin = isCN
+      ? helper.spin("Signing in leetcode.cn")
+      : helper.spin("Signing in leetcode.com");
     let that = this;
     request(config.sys.urls.login, function (e, resp, _) {
       spin.stop();
       e = that.checkError(e, resp, 200);
       if (e) return cb(e);
 
-      user.loginCSRF = helper.getSetCookieValue(resp, 'csrftoken');
+      user.loginCSRF = helper.getSetCookieValue(resp, "csrftoken");
 
       const opts = {
         url: config.sys.urls.login,
         headers: {
           Origin: config.sys.urls.base,
           Referer: config.sys.urls.login,
-          Cookie: 'csrftoken=' + user.loginCSRF + ';'
+          Cookie: "csrftoken=" + user.loginCSRF + ";",
         },
         form: {
           csrfmiddlewaretoken: user.loginCSRF,
           login: user.login,
-          password: user.pass
-        }
+          password: user.pass,
+        },
       };
       request.post(opts, function (e, resp, _) {
         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');
+        user.sessionCSRF = helper.getSetCookieValue(resp, "csrftoken");
+        user.sessionId = helper.getSetCookieValue(resp, "LEETCODE_SESSION");
         session.saveUser(user);
         return cb(null, user);
       });
@@ -517,15 +517,17 @@ 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?');
+          log.warn("Favorite not found?");
         }
       } else {
-        log.warn('Failed to retrieve user favorites: ' + e);
+        log.warn("Failed to retrieve user favorites: " + e);
       }
 
       that.getUserInfo(function (e, _user) {
@@ -553,7 +555,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],
@@ -566,7 +568,7 @@ class LeetCode extends MyPluginBase {
     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.');
+        return cb("Login failed. Please make sure the credential is correct.");
       }
       const cookieData = that.parseCookie(resp.request.headers.cookie, cb);
       user.sessionId = cookieData.sessionId;
@@ -590,84 +592,92 @@ class LeetCode extends MyPluginBase {
     const _request = request.defaults({ jar: true });
     let that = this;
     _request(urls.github_login_request, function (_, __, body) {
-
-      const authenticityToken = body.match(/name="authenticity_token" value="(.*?)"/);
+      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');
+      const timestampSecret = body.match(
+        /name="timestamp_secret" value="(.*?)"/
+      );
+
+      if (
+        !(authenticityToken && timestamp && timestampSecret && requiredField)
+      ) {
+        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',
+        prompt_out.get(
+          [
+            {
+              name: "twoFactorCode",
+              required: true,
             },
-            followAllRedirects: true,
-            form: {
-              'otp': result.twoFactorCode,
-              'authenticity_token': authenticityTokenTwoFactor[1],
-              'utf8': encodeURIComponent('✓'),
-            },
-          };
-          _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 log.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("✓"),
+              },
+            };
+            _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);
+            });
+          }
+        );
       });
     });
   };
@@ -678,60 +688,64 @@ class LeetCode extends MyPluginBase {
     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="(.*?)"/);
+      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",
         },
       };
       _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/childProcessCall/plugins/retry.ts
index 8ca06fa..aba1696 100644
--- a/src/childProcessCall/plugins/retry.ts
+++ b/src/childProcessCall/plugins/retry.ts
@@ -7,38 +7,37 @@
  * Copyright (c) 2022 ccagml . All rights reserved.
  */
 
-
-
 import { MyPluginBase } from "../my_plugin_base";
 import { config } from "../config";
 import { session } from "../session";
 
-
 class RetryPlugin extends MyPluginBase {
   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 (
+      config.autologin.enable &&
+      e === session.errors.EXPIRED &&
+      (this.count[name] || 0) < config.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();
     if (!user) {
-
       return cb();
     }
 
@@ -89,8 +86,6 @@ class RetryPlugin extends MyPluginBase {
       return cb();
     });
   };
-
 }
 
-
 export const pluginObj: RetryPlugin = new RetryPlugin();
diff --git a/src/childProcessCall/plugins/solution.discuss.ts b/src/childProcessCall/plugins/solution.discuss.ts
index ac24a4f..7b439d8 100644
--- a/src/childProcessCall/plugins/solution.discuss.ts
+++ b/src/childProcessCall/plugins/solution.discuss.ts
@@ -7,16 +7,12 @@
  * Copyright (c) 2022 ccagml . All rights reserved.
  */
 
-
-let request = require('request');
-
+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";
@@ -25,19 +21,22 @@ class SolutionDiscuss extends MyPluginBase {
     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);
+        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');
+        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);
@@ -46,68 +45,67 @@ class SolutionDiscuss extends MyPluginBase {
         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("* 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';
+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';
+  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',
+        "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: '',
+        query: "",
         first: 1,
         skip: 0,
-        orderBy: 'most_votes',
-        questionId: '' + problem.id,
-        tags: [lang]
-      })
-    }
+        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 });
+      return cb({ msg: "http error", statusCode: resp.statusCode });
 
     const solutions = body.data.questionTopicsList.edges;
     const solution = solutions.length > 0 ? solutions[0].node : null;
diff --git a/src/childProcessCall/queue.ts b/src/childProcessCall/queue.ts
index 1db7165..0488210 100644
--- a/src/childProcessCall/queue.ts
+++ b/src/childProcessCall/queue.ts
@@ -7,9 +7,7 @@
  * Copyright (c) 2022 ccagml . All rights reserved.
  */
 
-
-
-let underscore = require('underscore');
+let underscore = require("underscore");
 
 import { config } from "./config";
 
@@ -30,12 +28,12 @@ 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;
@@ -43,9 +41,11 @@ export class Queue {
 
     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
@@ -61,8 +61,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/childProcessCall/session.ts
index d1737c3..2999008 100644
--- a/src/childProcessCall/session.ts
+++ b/src/childProcessCall/session.ts
@@ -7,10 +7,8 @@
  * 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";
@@ -19,13 +17,12 @@ import { helper } from "./helper";
 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);
   };
@@ -33,7 +30,10 @@ class Session {
   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']);
+    const _user = underscore.omit(
+      user,
+      config.autologin.enable ? [] : ["pass"]
+    );
     storageUtils.setCache(helper.KEYS.user, _user);
   };
 
@@ -47,15 +47,15 @@ class Session {
 
   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 today = moment_out().format("YYYY-MM-DD");
     const stats = storageUtils.getCache(helper.KEYS.stat) || {};
-    const stat = stats[today] = stats[today] || {};
+    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);
diff --git a/src/childProcessCall/storageUtils.ts b/src/childProcessCall/storageUtils.ts
index aae8e5e..db4a1f0 100644
--- a/src/childProcessCall/storageUtils.ts
+++ b/src/childProcessCall/storageUtils.ts
@@ -7,18 +7,17 @@
  * Copyright (c) 2022 ccagml . All rights reserved.
  */
 
+let fs = require("fs");
+let os = require("os");
+let path = require("path");
 
-let fs = require('fs');
-let os = require('os');
-let path = require('path');
-
-let _ = require('underscore');
-let mkdirp = require('mkdirp');
+let _ = require("underscore");
+let mkdirp = require("mkdirp");
 
 export interface IMETA {
-  id: string
-  fid: string
-  lang: string
+  id: string;
+  fid: string;
+  lang: string;
 }
 
 //Object.assign({}, defaultMETA, {})
@@ -32,42 +31,42 @@ class StorageUtils {
   public init() {
     _.templateSettings = {
       evaluate: /\{\{(.+?)\}\}/g,
-      interpolate: /\$\{(.+?)\}/g
+      interpolate: /\$\{(.+?)\}/g,
     };
     this.mkdir(this.homeDir());
-  };
+  }
 
   public isWindows() {
-    return process.platform === 'win32';
-  };
+    return process.platform === "win32";
+  }
 
   public userHomeDir() {
     return process.env.HOME || process.env.USERPROFILE;
-  };
+  }
 
   public homeDir() {
-    return path.join(this.userHomeDir(), '.lcpr');
-  };
+    return path.join(this.userHomeDir(), ".lcpr");
+  }
 
   public appDir() {
-    const config = require('./config');
-    return path.join(this.homeDir(), config.app || 'leetcode');
-  };
+    const config = require("./config");
+    return path.join(this.homeDir(), config.app || "leetcode");
+  }
 
   // 缓存目录
   public cacheDir() {
-    return path.join(this.appDir(), 'cache');
-  };
+    return path.join(this.appDir(), "cache");
+  }
 
   // 代码目录
   public codeDir(dir) {
-    return path.join(__dirname, dir || '');
-  };
+    return path.join(__dirname, dir || "");
+  }
 
   // 缓存目录文件
   public cacheFile(k) {
-    return path.join(this.cacheDir(), k + '.json');
-  };
+    return path.join(this.cacheDir(), k + ".json");
+  }
 
   // public configFile() {
   //   return path.join(this.homeDir(), 'config.json');
@@ -84,35 +83,38 @@ class StorageUtils {
 
       let data = null;
       switch (ext) {
-        case '.js': data = require(fullpath).pluginObj; break;
-        case '.json': data = JSON.parse(that.getData(fullpath)); break;
+        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.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);
@@ -120,59 +122,61 @@ class StorageUtils {
 
     this.rm(fullpath);
     return true;
-  };
+  }
 
   public listCache(): Array {
     let that = this;
     return this.list(this.cacheDir())
-      .filter(x => path.extname(x) === '.json')
+      .filter((x) => path.extname(x) === ".json")
       .map(function (filename) {
-        const k = path.basename(filename, '.json');
+        const k = path.basename(filename, ".json");
         const stat = that.stat(that.cacheFile(k));
         return {
           name: k,
           size: stat.size,
-          mtime: stat.mtime
+          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;
-  };
+    return fs.existsSync(fullpath)
+      ? fs.readFileSync(fullpath).toString()
+      : null;
+  }
 
   // 获取要提交测试的数据
   public codeData(fullpath) {
@@ -183,38 +187,45 @@ class StorageUtils {
     }
 
     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);
+    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);
+    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');
+      result = result.replace(/\n/g, "\r\n");
     } else {
-      result = result.replace(/\r\n/g, '\n');
+      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
@@ -225,18 +236,20 @@ class StorageUtils {
 
   public meta(filename) {
     const m = Object.assign({}, defaultMETA, {});
-    const line = this.getData(filename).split('\n').find(x => x.indexOf(' @lc app=') >= 0) || '';
+    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_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..b6c2fca 100644
--- a/src/controller/FileButtonController.ts
+++ b/src/controller/FileButtonController.ts
@@ -7,31 +7,43 @@
  * Copyright (c) 2022 ccagml . All rights reserved.
  */
 
-
-import { ConfigurationChangeEvent, Disposable, languages, workspace } from "vscode";
+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();
+export const fileButtonController: FileButtonController =
+  new FileButtonController();
diff --git a/src/controller/LoginController.ts b/src/controller/LoginController.ts
index 2d50c0c..944d1bc 100644
--- a/src/controller/LoginController.ts
+++ b/src/controller/LoginController.ts
@@ -10,7 +10,13 @@
 import * as cp from "child_process";
 import * as systemUtils from "../utils/SystemUtils";
 import { executeService } from "../service/ExecuteService";
-import { DialogType, Endpoint, IQuickItemEx, loginArgsMapping, UserStatus } from "../model/Model";
+import {
+  DialogType,
+  Endpoint,
+  IQuickItemEx,
+  loginArgsMapping,
+  UserStatus,
+} from "../model/Model";
 import { createEnvOption } from "../utils/CliUtils";
 import { logOutput, promptForOpenOutputChannel } from "../utils/OutputUtils";
 import { eventService } from "../service/EventService";
@@ -19,172 +25,200 @@ 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);
+  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.stdin?.write(`${pwd}\n`);
-            });
-            if (userName) {
-                window.showInformationMessage(`${inMessage} 成功`);
-                eventService.emit("statusChanged", UserStatus.SignedIn, userName);
+              );
+            }
+          }
+
+          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) {
+        window.showInformationMessage(`${inMessage} 成功`);
+        eventService.emit("statusChanged", UserStatus.SignedIn, userName);
+      }
+    } catch (error) {
+      promptForOpenOutputChannel(
+        `${inMessage}失败. 请看看控制台输出信息`,
+        DialogType.error
+      );
     }
-
-    // 获取登录状态
-    public async getLoginStatus() {
-        return await statusBarService.getLoginStatus();
+  }
+
+  // 登出
+  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 deleteAllCache(): Promise {
-        await this.signOut();
-        await executeService.removeOldCache();
-        await executeService.switchEndpoint(getLeetCodeEndpoint());
-        await treeDataService.refresh();
-    }
-
+  }
+
+  // 获取登录状态
+  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..a3f5a0f 100644
--- a/src/controller/MainController.ts
+++ b/src/controller/MainController.ts
@@ -14,29 +14,28 @@ import { treeDataService } from "../service/TreeDataService";
 
 // 做杂活
 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 initialize(context: ExtensionContext) {
-        treeDataService.initialize(context);
+  /**
+   * 检查运行环境
+   */
+  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 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..3500b0c 100644
--- a/src/controller/TreeViewController.ts
+++ b/src/controller/TreeViewController.ts
@@ -7,25 +7,73 @@
  * 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 {
+  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 { NodeModel } from "../model/NodeModel";
 import { ISearchSet } from "../model/Model";
 import { statusBarService } from "../service/StatusBarService";
 import { previewService } from "../service/PreviewService";
 import { executeService } from "../service/ExecuteService";
 import { getNodeIdFromFile } from "../utils/SystemUtils";
-import { logOutput, promptForOpenOutputChannel, promptForSignIn, promptHintMessage } from "../utils/OutputUtils";
+import {
+  logOutput,
+  promptForOpenOutputChannel,
+  promptForSignIn,
+  promptHintMessage,
+} from "../utils/OutputUtils";
 import { treeDataService } from "../service/TreeDataService";
 import { genFileExt, genFileName } from "../utils/SystemUtils";
-import { IDescriptionConfiguration, isStarShortcut } from "../utils/ConfigUtils";
+import {
+  IDescriptionConfiguration,
+  isStarShortcut,
+} from "../utils/ConfigUtils";
 import * as systemUtils from "../utils/SystemUtils";
 import { solutionService } from "../service/SolutionService";
 import { eventService } from "../service/EventService";
@@ -34,1422 +82,1740 @@ 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<
+    string,
+    NodeModel
+  >();
+  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;
+    }
+    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;
+  }
+
+  // 提交问题
+  public async submitSolution(uri?: vscode.Uri): Promise {
+    if (!statusBarService.getUser()) {
+      promptForSignIn();
+      return;
     }
 
+    const filePath: string | undefined = await this.getActiveFilePath(uri);
+    if (!filePath) {
+      return;
+    }
 
-    // 提交测试用例
-    public async testSolution(uri?: vscode.Uri): Promise {
-        try {
-            if (statusBarService.getStatus() === UserStatus.SignedOut) {
-                return;
-            }
+    try {
+      const result: string = await executeService.submitSolution(filePath);
+      submissionService.show(result);
+      eventService.emit("submit", submissionService.getSubmitEvent());
+    } catch (error) {
+      await promptForOpenOutputChannel(
+        "提交出错了. 请查看控制台信息~",
+        DialogType.error
+      );
+      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",
-                // },
+    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)
             );
-            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;
+          }
+          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."
+              );
             }
-            submissionService.show(result);
-            eventService.emit("submit", submissionService.getSubmitEvent());
-        } catch (error) {
-            await promptForOpenOutputChannel("提交测试出错了. 请查看控制台信息~", DialogType.error);
-        }
+          }
+          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 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 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 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 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 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;
+    if (comSpec.indexOf("cmd.exe") > -1) {
+      return true;
     }
-
-    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, '\"')}`;
-            }
-            return `'${test.replace(/"/g, '\\"')}'`;
-        }
+    return false;
+  }
+
+  public parseTestString(test: string): string {
+    if (systemUtils.useWsl() || !systemUtils.isWindows()) {
+      if (systemUtils.useVscodeNode()) {
+        return `${test}`;
+      }
+      return `'${test}'`;
     }
 
-
-    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);
-        }
+    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 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 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;
     }
-
-
-    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);
-        }
+    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
+      );
     }
 
-    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);
-        }
+    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 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 [];
-        }
+    const choice: IQuickItemEx | undefined =
+      await vscode.window.showQuickPick(picks);
+    if (!choice || choice.value === currentStrategy) {
+      return;
     }
 
-    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;
-        }
+    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 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,
+  }
+
+  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,
+      });
     }
-
-
-    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();
-        }
-
+    // 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;
     }
 
-    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();
-        }
-
-        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);
-        }
+    leetCodeConfig.update(
+      "defaultLanguage",
+      selectedItem.label,
+      true /* Global */
+    );
+    window.showInformationMessage(`设置默认语言 ${selectedItem.label} 成功`);
+  }
+
+  public isSubFolder(from: string, to: string): boolean {
+    const relative: string = path.relative(from, to);
+    if (relative === "") {
+      return true;
     }
-
-
-
-    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);
-        }
+    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;
     }
 
-
-    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);
+    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 showProblem(node?: NodeModel): Promise {
-        if (!node) {
-            return;
-        }
-        await this.showProblemInternal(node);
+  public async searchProblem(): Promise {
+    if (!statusBarService.getUser()) {
+      promptForSignIn();
+      return;
     }
 
-
-    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);
-        }
+    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;
     }
-
-    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;
+    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 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 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 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);
-        }
+    if (!problemInput) {
+      vscode.window.showErrorMessage(
+        "Invalid input to fetch the solution data."
+      );
+      return;
     }
 
-    public async showDescriptionView(node: IProblem): Promise {
-        return this.previewProblem(node, enableSideMode());
+    const language: string | undefined = await this.fetchProblemLanguage();
+    if (!language) {
+      return;
     }
-
-    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);
+    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 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",
-        });
+  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);
+  }
 
-        // 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 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 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;
+  }
+
+  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;
+      }
     }
 
-    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",
-        });
+    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 "";
+      }
+    }
 
-        // vscode.window.showErrorMessage(twoFactor || "输入错误");
+    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 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;
+    }
+    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;
+    }
+    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 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: twoFactor,
-            type: SearchSetType.Context,
-            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 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 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);
-        }
-    }
-
-
-
-
-    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}`,
+  }
+
+  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}`,
+                detail:
+                  ((problem.scoreData?.score || "0") > "0"
+                    ? "score: " + problem.scoreData?.score + " , "
+                    : "") +
+                  `AC rate: ${problem.passRate}, Difficulty: ${problem.difficulty}`,
                 value: problem,
-            }));
-            resolve(picks);
-        });
+              }
+            )
+        );
+        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 parseProblemDecorator(state: ProblemState, locked: boolean): string {
-        switch (state) {
-            case ProblemState.AC:
-                return "$(check) ";
-            case ProblemState.NotAC:
-                return "$(x) ";
-            default:
-                return locked ? "$(lock) " : "";
-        }
+  }
+
+  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 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);
-            }
-        });
+    let company: string = "";
+    if (/\$\{company\}/i.test(relativePath)) {
+      company = (await this.resolveCompanyForProblem(node)) || "";
     }
 
-    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,
-            },
-        );
+    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 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,
-        });
+    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 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();
+    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;
             }
+          }
         }
+      });
+      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();
-        }
+  public async refreshCheck(): Promise {
+    if (!statusBarService.getUser()) {
+      return;
     }
-
-    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);
-                }
-            });
+    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;
         }
-        return this.applySortingStrategy(sorceNode);
+      }
+    });
+    if (need_get_today && !this.waitTodayQuestion) {
+      this.waitTodayQuestion = true;
+      await this.searchToday();
     }
-
-    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);
+    let user_score = statusBarService.getUserContestScore();
+    if (!user_score && !this.waitUserContest) {
+      this.waitUserContest = true;
+      await this.searchUserContest();
     }
-
-    public getAllNodes(): NodeModel[] {
-        return this.applySortingStrategy(
-            Array.from(this.explorerNodeMap.values()).filter(p => this.canShow(p)),
+  }
+
+  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);
+  }
 
-    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;
-    }
-
-    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.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 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.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 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;
+    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 getNodeById(id: string): NodeModel | undefined {
-        return this.explorerNodeMap.get(id);
+    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 getFavoriteNodes(): NodeModel[] {
-        const res: NodeModel[] = [];
-        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);
             }
-            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;
-            }
-            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..5efc4f6 100644
--- a/src/dao/choiceDao.ts
+++ b/src/dao/choiceDao.ts
@@ -8,2088 +8,327 @@
  */
 
 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..05d00e2 100644
--- a/src/dao/tagsDao.ts
+++ b/src/dao/tagsDao.ts
@@ -7,2892 +7,7178 @@
  * 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..f20045c 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,109 @@ 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.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..e4c3b52 100644
--- a/src/model/NodeModel.ts
+++ b/src/model/NodeModel.ts
@@ -7,137 +7,145 @@
  * Copyright (c) 2022 ccagml . All rights reserved.
  */
 
-
 import { Command, Uri } from "vscode";
-import { IProblem, IScoreData, ITodayData, ProblemState, RootNodeSort } from "./Model";
+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/service/BaseWebviewService.ts b/src/service/BaseWebviewService.ts
index 3646604..02446e8 100644
--- a/src/service/BaseWebviewService.ts
+++ b/src/service/BaseWebviewService.ts
@@ -7,80 +7,104 @@
  * Copyright (c) 2022 ccagml . All rights reserved.
  */
 
-
-import { commands, ConfigurationChangeEvent, Disposable, ViewColumn, WebviewPanel, window, workspace } from "vscode";
+import {
+  commands,
+  ConfigurationChangeEvent,
+  Disposable,
+  ViewColumn,
+  WebviewPanel,
+  window,
+  workspace,
+} from "vscode";
 import { markdownService } from "./MarkdownService";
 import { IWebViewOption } from "../model/Model";
 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..eb7ab24 100644
--- a/src/service/ExecuteService.ts
+++ b/src/service/ExecuteService.ts
@@ -7,14 +7,25 @@
  * Copyright (c) 2022 ccagml . All rights reserved.
  */
 
-
 import * as cp from "child_process";
 import * as fse from "fs-extra";
 import * as os from "os";
 import * as path from "path";
 import { ExtensionContext } from "vscode";
-import { ConfigurationChangeEvent, Disposable, MessageItem, window, workspace } from "vscode";
-import { DialogOptions, DialogType, Endpoint, IProblem, leetcodeHasInited } from "../model/Model";
+import {
+  ConfigurationChangeEvent,
+  Disposable,
+  MessageItem,
+  window,
+  workspace,
+} from "vscode";
+import {
+  DialogOptions,
+  DialogType,
+  Endpoint,
+  IProblem,
+  leetcodeHasInited,
+} from "../model/Model";
 import { executeCommand, executeCommandWithProgress } from "../utils/CliUtils";
 import { getNodePath } from "../utils/ConfigUtils";
 import { openUrl, promptForOpenOutputChannel } from "../utils/OutputUtils";
@@ -22,253 +33,447 @@ 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");
-        this.nodeExecutable = this.initNodePath();
-        this.configurationChangeListener = workspace.onDidChangeConfiguration((event: ConfigurationChangeEvent) => {
-            if (event.affectsConfiguration("leetcode-problem-rating.nodePath")) {
-                this.nodeExecutable = this.initNodePath();
-            }
-        }, this);
+  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"
+      );
     }
-
-    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")}"`;
+    this.leetCodeCliRootPath = path.join(
+      __dirname,
+      "..",
+      "..",
+      "..",
+      "out",
+      "src",
+      "childProcessCall"
+    );
+    this.nodeExecutable = this.initNodePath();
+    this.configurationChangeListener = workspace.onDidChangeConfiguration(
+      (event: ConfigurationChangeEvent) => {
+        if (event.affectsConfiguration("leetcode-problem-rating.nodePath")) {
+          this.nodeExecutable = this.initNodePath();
         }
+      },
+      this
+    );
+  }
+
+  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();
-        }
-        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;
+  public async checkNodeEnv(context: ExtensionContext): Promise {
+    const hasInited: boolean | undefined =
+      context.globalState.get(leetcodeHasInited);
+    if (!hasInited) {
+      await this.removeOldCache();
     }
-
-    public async deleteCache() {
-        try {
-            await this.executeCommandEx(this.nodeExecutable, [await this.getLeetCodeBinaryPath(), "cache", "-d"]);
-        } catch (error) {
-            await promptForOpenOutputChannel("Failed to delete cache. 请查看控制台信息~", DialogType.error);
-        }
+    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 getUserInfo(): Promise {
-        return await this.executeCommandEx(this.nodeExecutable, [await this.getLeetCodeBinaryPath(), "user"]);
+    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 signOut(): Promise {
-        return await this.executeCommandEx(this.nodeExecutable, [await this.getLeetCodeBinaryPath(), "user", "-L"]);
+    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 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 getUserInfo(): Promise {
+    return await this.executeCommandEx(this.nodeExecutable, [
+      await this.getLeetCodeBinaryPath(),
+      "user",
+    ]);
+  }
+
+  public async signOut(): Promise {
+    return await this.executeCommandEx(this.nodeExecutable, [
+      await this.getLeetCodeBinaryPath(),
+      "user",
+      "-L",
+    ]);
+  }
+
+  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 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);
-        }
+    if (!showLocked) {
+      cmd.push("-q");
+      cmd.push("L");
     }
-
-
-    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;
+    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 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;
+    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 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 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 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;
+    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 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 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 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 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 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;
-        }
+    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 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}"`]);
+  }
+
+  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 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"]);
-        }
+    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 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 (systemUtils.useVscodeNode()) {
+      return await this.executeCommandWithProgressEx(
+        "Submitting to LeetCode...",
+        this.nodeExecutable,
+        [await this.getLeetCodeBinaryPath(), "test", `${filePath}`]
+      );
     }
-
-
-    public get node(): string {
-        return this.nodeExecutable;
+    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",
+        ]);
     }
-
-    public dispose(): void {
-        this.configurationChangeListener.dispose();
+  }
+
+  public async toggleFavorite(
+    node: IProblem,
+    addToFavorite: boolean
+  ): Promise {
+    const commandParams: string[] = [
+      await this.getLeetCodeBinaryPath(),
+      "star",
+      node.id,
+    ];
+    if (!addToFavorite) {
+      commandParams.push("-d");
     }
-
-    private initNodePath(): string {
-        if (systemUtils.useVscodeNode()) {
-            return "node";
-        }
-        return getNodePath();
+    await this.executeCommandWithProgressEx(
+      "Updating the favorite list...",
+      "node",
+      commandParams
+    );
+  }
+
+  public get node(): string {
+    return this.nodeExecutable;
+  }
+
+  public dispose(): void {
+    this.configurationChangeListener.dispose();
+  }
+
+  private initNodePath(): string {
+    if (systemUtils.useVscodeNode()) {
+      return "node";
     }
-
-    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);
+    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);
     }
-
-    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);
+    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);
-        }
+  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..bc79acd 100644
--- a/src/service/FileButtonService.ts
+++ b/src/service/FileButtonService.ts
@@ -13,103 +13,128 @@ 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();
+  }
+
+  public provideCodeLenses(
+    document: vscode.TextDocument
+  ): vscode.ProviderResult {
+    const shortcuts: string[] = getEditorShortcuts();
+    if (!shortcuts) {
+      return;
+    }
 
-    private onDidChangeCodeLensesEmitter: vscode.EventEmitter = new vscode.EventEmitter();
+    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);
+    }
 
-    get onDidChangeCodeLenses(): vscode.Event {
-        return this.onDidChangeCodeLensesEmitter.event;
+    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;
+      }
     }
 
-    public refresh(): void {
-        this.onDidChangeCodeLensesEmitter.fire();
+    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],
+        })
+      );
     }
 
-    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("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;
+  }
 }
 
 export const fileButtonService: FileButtonService = new FileButtonService();
diff --git a/src/service/MarkdownService.ts b/src/service/MarkdownService.ts
index a2e8405..c0190c2 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,203 @@ 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() {
-        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();
-    }
-
-    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.");
+  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();
         }
-        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:"); - }; + }, + 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." + ); } + 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:"); + }; + } } // 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..d997cfd 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,54 @@ 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 +140,101 @@ 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..df40be3 100644 --- a/src/service/StatusBarService.ts +++ b/src/service/StatusBarService.ts @@ -7,8 +7,13 @@ * Copyright (c) 2022 ccagml . All rights reserved. */ - -import { ConfigurationChangeEvent, Disposable, workspace, StatusBarItem, window } from "vscode"; +import { + ConfigurationChangeEvent, + Disposable, + workspace, + StatusBarItem, + window, +} from "vscode"; import { UserStatus, userContestRanKingBase } from "../model/Model"; import { enableStatusBar } from "../utils/ConfigUtils"; import { eventService } from "./EventService"; @@ -16,121 +21,140 @@ 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; + } + private tryParseUserName(output: string): string | undefined { + let successMatch; + try { + successMatch = JSON.parse(output); + } catch (e) { + successMatch = {}; } - public update_UserContestInfo(UserContestInfo?: userContestRanKingBase | undefined) { - this.currentUserContestInfo = UserContestInfo; + if (successMatch.code == 100) { + return successMatch.user_name; } - - // 更新数据 - 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(); + return undefined; + } + + constructor() { + this.instance = window.createStatusBarItem(); + this.setStatusBarVisibility(); + 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.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..146caed 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,40 @@ 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 +62,37 @@ 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..b1b4d01 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,189 @@ 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< + NodeModel | undefined | null + > = 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; + } + + 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..8c3b8d7 100644 --- a/src/service/TreeItemDecorationService.ts +++ b/src/service/TreeItemDecorationService.ts @@ -7,81 +7,89 @@ * 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(); +export const treeItemDecorationService: TreeItemDecorationService = + new TreeItemDecorationService(); diff --git a/src/utils/CliUtils.ts b/src/utils/CliUtils.ts index 07d8d2e..7577a54 100644 --- a/src/utils/CliUtils.ts +++ b/src/utils/CliUtils.ts @@ -7,93 +7,122 @@ * 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() }); +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]); } - - childProc.stdout?.on("data", (data: string | Buffer) => { - data = data.toString(); - result = result.concat(data); - logOutput.append(data); + 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; } // 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(); + if (proxy) { + const env: any = Object.create(process.env); + env.http_proxy = proxy; + return env; + } + return process.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..93fbd98 100644 --- a/src/utils/ConfigUtils.ts +++ b/src/utils/ConfigUtils.ts @@ -7,156 +7,180 @@ * Copyright (c) 2022 ccagml . All rights reserved. */ - - import { workspace, WorkspaceConfiguration, commands } from "vscode"; -import { DescriptionConfiguration, Endpoint, IProblem, SortingStrategy } from "../model/Model"; +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; +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; } // 随机题目最小分数 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..1790c69 100644 --- a/src/utils/OutputUtils.ts +++ b/src/utils/OutputUtils.ts @@ -7,92 +7,115 @@ * 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, + 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; - } + 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; - } +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; + } - 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); - } + 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(); + } } export const logOutput: LogOutput = new LogOutput(); diff --git a/src/utils/SystemUtils.ts b/src/utils/SystemUtils.ts index 419ab81..3162f98 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,70 @@ 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; } From 9ad07683ae8a06d6593ba0e3e15c73b7cbb004be Mon Sep 17 00:00:00 2001 From: ccagml Date: Wed, 16 Nov 2022 17:25:45 +0800 Subject: [PATCH 02/26] =?UTF-8?q?=E5=8F=96=E5=87=BA=E5=A4=9A=E4=BD=99?= =?UTF-8?q?=E7=9A=84=E5=8C=85=20=E5=A2=9E=E5=8A=A0=E7=8E=AF=E5=A2=83?= =?UTF-8?q?=E5=8F=98=E9=87=8F=E4=BC=A0=E9=80=92?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package-lock.json | 1496 ++++++----------- package.json | 1 - src/childProcessCall/cli.ts | 3 +- .../{helper.ts => commUtils.ts} | 117 +- src/childProcessCall/commands/cache.ts | 4 +- src/childProcessCall/commands/config.ts | 4 +- src/childProcessCall/commands/list.ts | 4 +- src/childProcessCall/commands/plugin.ts | 4 +- src/childProcessCall/commands/query.ts | 4 +- src/childProcessCall/commands/session.ts | 4 +- src/childProcessCall/commands/show.ts | 14 +- src/childProcessCall/commands/star.ts | 4 +- src/childProcessCall/commands/stat.ts | 8 +- src/childProcessCall/commands/submission.ts | 6 +- src/childProcessCall/commands/submit.ts | 4 +- src/childProcessCall/commands/test.ts | 6 +- src/childProcessCall/commands/user.ts | 4 +- src/childProcessCall/config.ts | 5 +- src/childProcessCall/core.ts | 3 +- src/childProcessCall/my_plugin_base.ts | 8 +- src/childProcessCall/plugins/cache.ts | 22 +- src/childProcessCall/plugins/leetcode.ts | 17 +- src/childProcessCall/session.ts | 14 +- src/childProcessCall/storageUtils.ts | 145 +- src/controller/MainController.ts | 13 + src/utils/CliUtils.ts | 9 +- src/utils/OutputUtils.ts | 13 + 27 files changed, 723 insertions(+), 1213 deletions(-) rename src/childProcessCall/{helper.ts => commUtils.ts} (59%) diff --git a/package-lock.json b/package-lock.json index 4c850f1..75f20cb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -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", @@ -79,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", @@ -110,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", @@ -212,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": { @@ -245,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", @@ -277,36 +308,6 @@ } } }, - "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.43.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.43.0.tgz", @@ -334,7 +335,7 @@ } } }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": { + "node_modules/@typescript-eslint/scope-manager": { "version": "5.43.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.43.0.tgz", "integrity": "sha512-XNWnGaqAtTJsUiZaoiGIrdJYHsUOd3BZ3Qj5zKp9w6km6HsrjPk/TGZv0qMTWyWj0+1QOqpHQ2gZOLXaGA9Ekw==", @@ -351,118 +352,14 @@ "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": { - "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" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": { - "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.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" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": { - "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.43.0", - "eslint-visitor-keys": "^3.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/parser/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/parser/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/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==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.42.1", - "@typescript-eslint/visitor-keys": "5.42.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, "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" }, @@ -482,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" @@ -511,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", @@ -537,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" @@ -593,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": { @@ -662,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": { @@ -812,30 +649,66 @@ "integrity": "sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw==", "dev": true, "dependencies": { - "assertion-error": "^1.1.0", - "check-error": "^1.0.2", - "deep-eql": "^3.0.1", - "get-func-name": "^2.0.0", - "pathval": "^1.1.0", - "type-detect": "^4.0.5" + "assertion-error": "^1.1.0", + "check-error": "^1.0.2", + "deep-eql": "^3.0.1", + "get-func-name": "^2.0.0", + "pathval": "^1.1.0", + "type-detect": "^4.0.5" + }, + "engines": { + "node": ">=4" + } + }, + "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/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": ">=4" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "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==", + "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": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "color-name": "~1.1.4" }, "engines": { - "node": ">=4" + "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", @@ -881,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", @@ -910,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", @@ -1080,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", @@ -1217,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": { @@ -1329,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", @@ -1421,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", @@ -1872,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": { @@ -2073,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", @@ -2192,17 +1888,6 @@ "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" - } - }, "node_modules/lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", @@ -2284,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", @@ -2397,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", @@ -2425,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", @@ -2744,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", @@ -2842,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": { @@ -2871,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", @@ -2936,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": { @@ -2984,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": { @@ -3072,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", @@ -3084,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==", @@ -3096,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", @@ -3222,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", @@ -3246,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", @@ -3262,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", @@ -3296,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", @@ -3334,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", @@ -3428,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": { @@ -3450,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": { @@ -3534,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": { @@ -3567,40 +3277,20 @@ "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": { @@ -3613,177 +3303,74 @@ "@typescript-eslint/types": "5.43.0", "@typescript-eslint/typescript-estree": "5.43.0", "debug": "^4.3.4" - }, - "dependencies": { - "@typescript-eslint/scope-manager": { - "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.43.0", - "@typescript-eslint/visitor-keys": "5.43.0" - } - }, - "@typescript-eslint/types": { - "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.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.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" - } - }, - "@typescript-eslint/visitor-keys": { - "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.43.0", - "eslint-visitor-keys": "^3.3.0" - } - }, - "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/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" - } - } } }, "@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" } }, @@ -3812,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", @@ -3944,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": { @@ -3986,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", @@ -4007,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", @@ -4137,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", @@ -4232,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", @@ -4283,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", @@ -4344,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" - } } } }, @@ -4721,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", @@ -4869,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": { @@ -4973,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", @@ -5043,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", @@ -5129,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", @@ -5151,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", @@ -5370,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", @@ -5424,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", @@ -5444,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", @@ -5490,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": { @@ -5513,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": { @@ -5527,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": { @@ -5591,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", @@ -5599,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" @@ -5704,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", @@ -5722,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", @@ -5735,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" + } } } }, @@ -5762,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", @@ -5787,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 6c34a45..1d13194 100644 --- a/package.json +++ b/package.json @@ -787,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/src/childProcessCall/cli.ts b/src/childProcessCall/cli.ts index dd3afa5..2ce1012 100644 --- a/src/childProcessCall/cli.ts +++ b/src/childProcessCall/cli.ts @@ -6,7 +6,6 @@ * * Copyright (c) 2022 ccagml . All rights reserved. */ -// var h = require('./helper'); import { myPluginBase } from "./my_plugin_base"; import { config } from "./config"; @@ -20,7 +19,7 @@ class NewCli { process.stdout.on("error", function (e) { if (e.code === "EPIPE") process.exit(); }); - config.init(); + config.init(JSON.parse(process.env.ccagml || "{}")); log.init(); storageUtils.init(); if (myPluginBase.base_init()) { diff --git a/src/childProcessCall/helper.ts b/src/childProcessCall/commUtils.ts similarity index 59% rename from src/childProcessCall/helper.ts rename to src/childProcessCall/commUtils.ts index da2df98..426841a 100644 --- a/src/childProcessCall/helper.ts +++ b/src/childProcessCall/commUtils.ts @@ -1,63 +1,15 @@ /* - * 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 + * Filename: /home/cc/vscode-leetcode-problem-rating/src/childProcessCall/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. */ -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 { +class CommUtils { KEYS; constructor() { this.KEYS = { @@ -71,33 +23,6 @@ class HELPER { }; } - // 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": @@ -149,29 +74,6 @@ class HELPER { } } - 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 = []; @@ -219,15 +121,6 @@ class HELPER { .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: {}, @@ -304,4 +197,4 @@ class HELPER { } } -export const helper: HELPER = new HELPER(); +export const commUtils: CommUtils = new CommUtils(); diff --git a/src/childProcessCall/commands/cache.ts b/src/childProcessCall/commands/cache.ts index e2a0be6..044723c 100644 --- a/src/childProcessCall/commands/cache.ts +++ b/src/childProcessCall/commands/cache.ts @@ -9,7 +9,7 @@ // let underscore = require('underscore'); -import { helper } from "../helper"; +import { commUtils } from "../commUtils"; // import { log } from "../log"; import { storageUtils } from "../storageUtils"; import { session } from "../session"; @@ -18,7 +18,7 @@ class CacheCommand { constructor() {} process_argv = function (argv) { - let argv_config = helper.base_argv().option("d", { + let argv_config = commUtils.base_argv().option("d", { alias: "delete", type: "boolean", describe: "Delete cache by keyword", diff --git a/src/childProcessCall/commands/config.ts b/src/childProcessCall/commands/config.ts index 6f2604f..11251d9 100644 --- a/src/childProcessCall/commands/config.ts +++ b/src/childProcessCall/commands/config.ts @@ -14,13 +14,13 @@ // import { log } from "../log"; // import { file } from "../file"; // import { session } from "../session"; -// import { helper } from "../helper"; +// import { commUtils } from "../commUtils"; class ConfigCommand { constructor() {} // process_argv(argv) { - // let argv_config = helper.base_argv().option('a', { + // let argv_config = commUtils.base_argv().option('a', { // alias: 'all', // type: 'boolean', // describe: 'Show all config', diff --git a/src/childProcessCall/commands/list.ts b/src/childProcessCall/commands/list.ts index 9bb0510..552a38c 100644 --- a/src/childProcessCall/commands/list.ts +++ b/src/childProcessCall/commands/list.ts @@ -7,7 +7,7 @@ * Copyright (c) 2022 ccagml . All rights reserved. */ -import { helper } from "../helper"; +import { commUtils } from "../commUtils"; import { log } from "../log"; import { corePlugin } from "../core"; import { session } from "../session"; @@ -16,7 +16,7 @@ class ListCommand { constructor() {} process_argv(argv) { - let argv_config = helper + let argv_config = commUtils .base_argv() .option("q", corePlugin.filters.query) .option("s", { diff --git a/src/childProcessCall/commands/plugin.ts b/src/childProcessCall/commands/plugin.ts index 87cdbc6..0634b6a 100644 --- a/src/childProcessCall/commands/plugin.ts +++ b/src/childProcessCall/commands/plugin.ts @@ -7,7 +7,7 @@ * Copyright (c) 2022 ccagml . All rights reserved. */ -import { helper } from "../helper"; +import { commUtils } from "../commUtils"; import { config } from "../config"; import { log } from "../log"; import { myPluginBase } from "../my_plugin_base"; @@ -17,7 +17,7 @@ class PluginCommand { constructor() {} process_argv = function (argv) { - let argv_config = helper + let argv_config = commUtils .base_argv() .option("d", { alias: "disable", diff --git a/src/childProcessCall/commands/query.ts b/src/childProcessCall/commands/query.ts index 9487b5d..a501d11 100644 --- a/src/childProcessCall/commands/query.ts +++ b/src/childProcessCall/commands/query.ts @@ -7,7 +7,7 @@ * Copyright (c) 2022 ccagml . All rights reserved. */ -import { helper } from "../helper"; +import { commUtils } from "../commUtils"; import { log } from "../log"; import { corePlugin } from "../core"; import { session } from "../session"; @@ -15,7 +15,7 @@ import { session } from "../session"; class QueryCommand { constructor() {} process_argv = function (argv) { - let argv_config = helper + let argv_config = commUtils .base_argv() .option("T", { alias: "dontTranslate", diff --git a/src/childProcessCall/commands/session.ts b/src/childProcessCall/commands/session.ts index fb50971..11f2258 100644 --- a/src/childProcessCall/commands/session.ts +++ b/src/childProcessCall/commands/session.ts @@ -7,7 +7,7 @@ * Copyright (c) 2022 ccagml . All rights reserved. */ -// import { helper } from "../helper"; +// import { commUtils } from "../commUtils"; // import { corePlugin } from "../core"; // import { log } from "../log"; // import { session } from "../session"; @@ -31,7 +31,7 @@ class SessionCommand { // submissionRate = s.total_acs * 100 / s.total_submitted; // log.info( - // s.is_active ? helper.prettyState('ac') : ' ', + // s.is_active ? commUtils.prettyState('ac') : ' ', // s.id, // s.name || 'Anonymous Session', // s.ac_questions, diff --git a/src/childProcessCall/commands/show.ts b/src/childProcessCall/commands/show.ts index 6d2b736..032d04f 100644 --- a/src/childProcessCall/commands/show.ts +++ b/src/childProcessCall/commands/show.ts @@ -10,7 +10,7 @@ let util = require("util"); let childProcess = require("child_process"); -import { helper } from "../helper"; +import { commUtils } from "../commUtils"; import { storageUtils } from "../storageUtils"; import { log } from "../log"; @@ -22,7 +22,7 @@ class ShowCommand { constructor() {} process_argv = function (argv) { - let argv_config = helper + let argv_config = commUtils .base_argv() .option("c", { alias: "codeonly", @@ -81,7 +81,7 @@ class ShowCommand { const params = [ storageUtils.fmt(config.file.show, problem), "", - helper.langToExt(opts.lang), + storageUtils.getFileExtByLanguage(opts.lang), ]; // try new name to avoid overwrite by mistake @@ -99,10 +99,10 @@ class ShowCommand { const taglist = [problem.category] .concat(problem.companies || []) .concat(problem.tags || []) - .map((x) => helper.badge(x)) + .map((x) => " " + x + " ") .join(" "); const langlist = problem.templates - .map((x) => helper.badge(x.value)) + .map((x) => " " + x.value + " ") .sort() .join(" "); @@ -156,7 +156,9 @@ class ShowCommand { log.info(); log.info(`* ${problem.category}`); log.info( - `* ${helper.prettyLevel(problem.level)} (${problem.percent.toFixed(2)}%)` + `* ${commUtils.prettyLevel(problem.level)} (${problem.percent.toFixed( + 2 + )}%)` ); if (problem.likes) log.info(`* Likes: ${problem.likes}`); diff --git a/src/childProcessCall/commands/star.ts b/src/childProcessCall/commands/star.ts index f9f97ba..99c164f 100644 --- a/src/childProcessCall/commands/star.ts +++ b/src/childProcessCall/commands/star.ts @@ -7,7 +7,7 @@ * Copyright (c) 2022 ccagml . All rights reserved. */ -import { helper } from "../helper"; +import { commUtils } from "../commUtils"; import { log } from "../log"; import { corePlugin } from "../core"; import { session } from "../session"; @@ -16,7 +16,7 @@ class StarCommand { constructor() {} process_argv(argv) { - let argv_config = helper + let argv_config = commUtils .base_argv() .option("d", { alias: "delete", diff --git a/src/childProcessCall/commands/stat.ts b/src/childProcessCall/commands/stat.ts index 5e0b7e1..949f242 100644 --- a/src/childProcessCall/commands/stat.ts +++ b/src/childProcessCall/commands/stat.ts @@ -10,7 +10,7 @@ // let moment_out = require('moment'); // let underscore = require('underscore'); -// import { helper } from "../helper"; +// import { commUtils } from "../commUtils"; // import { log } from "../log"; // import { corePlugin } from "../core"; // import { session } from "../session"; @@ -19,7 +19,7 @@ class StatCommand { constructor() {} // process_argv(argv) { - // let argv_config = helper.base_argv().option('c', { + // let argv_config = commUtils.base_argv().option('c', { // alias: 'cal', // type: 'boolean', // default: false, @@ -49,7 +49,7 @@ class StatCommand { // 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, + // commUtils.prettyLevel(key), done, all, // (100 * percent).toFixed(2), // '█'.repeat(x), // '░'.repeat(n - x)); @@ -141,7 +141,7 @@ class StatCommand { // // load historical stats // const graph: Array = []; - // const stats = require('../cache').get(helper.KEYS.stat) || {}; + // const stats = require('../cache').get(commUtils.KEYS.stat) || {}; // for (let k of underscore.keys(stats)) { // const score = (stats[k]['ac.set'] || []).reduce(toScore, 0); // if (score === 0) continue; diff --git a/src/childProcessCall/commands/submission.ts b/src/childProcessCall/commands/submission.ts index 614c23c..b4f0e79 100644 --- a/src/childProcessCall/commands/submission.ts +++ b/src/childProcessCall/commands/submission.ts @@ -11,7 +11,7 @@ // let _ = require('underscore'); -// import { helper } from "../helper"; +// import { commUtils } from "../commUtils"; // import { file } from "../file"; // import { config } from "../config"; // import { log } from "../log"; @@ -23,7 +23,7 @@ class SubMission { constructor() {} // process_argv = function (argv) { - // let argv_config = helper.base_argv().option('a', { + // let argv_config = commUtils.base_argv().option('a', { // alias: 'all', // type: 'boolean', // default: false, @@ -108,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 diff --git a/src/childProcessCall/commands/submit.ts b/src/childProcessCall/commands/submit.ts index 564151c..0a596b7 100644 --- a/src/childProcessCall/commands/submit.ts +++ b/src/childProcessCall/commands/submit.ts @@ -10,7 +10,7 @@ let util = require("util"); let lodash = require("lodash"); -import { helper } from "../helper"; +import { commUtils } from "../commUtils"; import { storageUtils } from "../storageUtils"; import { log } from "../log"; import { corePlugin } from "../core"; @@ -20,7 +20,7 @@ class SubmitCommand { constructor() {} process_argv(argv) { - let argv_config = helper.base_argv().positional("filename", { + let argv_config = commUtils.base_argv().positional("filename", { type: "string", describe: "Code file to submit", default: "", diff --git a/src/childProcessCall/commands/test.ts b/src/childProcessCall/commands/test.ts index 50a93da..1f61e0a 100644 --- a/src/childProcessCall/commands/test.ts +++ b/src/childProcessCall/commands/test.ts @@ -10,7 +10,7 @@ let _ = require("underscore"); let lodash = require("lodash"); -import { helper } from "../helper"; +import { commUtils } from "../commUtils"; import { storageUtils } from "../storageUtils"; import { log } from "../log"; import { corePlugin } from "../core"; @@ -20,7 +20,7 @@ class TestCommand { constructor() {} process_argv(argv) { - let argv_config = helper + let argv_config = commUtils .base_argv() .option("i", { alias: "interactive", @@ -234,7 +234,7 @@ class TestCommand { session.argv = argv; if (!argv.i) return that.runTest(argv); - helper.readStdin(function (e, data) { + commUtils.readStdin(function (e, data) { if (e) return log.info(e); argv.testcase = data; diff --git a/src/childProcessCall/commands/user.ts b/src/childProcessCall/commands/user.ts index b70e870..3a6e2ea 100644 --- a/src/childProcessCall/commands/user.ts +++ b/src/childProcessCall/commands/user.ts @@ -8,7 +8,7 @@ */ let prompt_out = require("prompt"); -import { helper } from "../helper"; +import { commUtils } from "../commUtils"; import { log } from "../log"; import { corePlugin } from "../core"; import { session } from "../session"; @@ -17,7 +17,7 @@ class UserCommand { constructor() {} process_argv(argv) { - let argv_config = helper + let argv_config = commUtils .base_argv() .option("l", { alias: "login", diff --git a/src/childProcessCall/config.ts b/src/childProcessCall/config.ts index e2b4b68..15d5ce4 100644 --- a/src/childProcessCall/config.ts +++ b/src/childProcessCall/config.ts @@ -10,6 +10,7 @@ let underscore = require("underscore"); class Config { + LCPTCTX; app; sys; autologin; @@ -105,7 +106,9 @@ class Config { this.plugins = {}; } - init() {} + init(ctx) { + this.LCPTCTX = ctx; + } getAll(useronly) { const cfg = underscore.extendOwn({}, this); diff --git a/src/childProcessCall/core.ts b/src/childProcessCall/core.ts index 4d0e1b9..660c2c6 100644 --- a/src/childProcessCall/core.ts +++ b/src/childProcessCall/core.ts @@ -13,7 +13,6 @@ let _ = require("underscore"); let cheerio = require("cheerio"); // import { log } from "./log"; -import { helper } from "./helper"; import { storageUtils } from "./storageUtils"; import { MyPluginBase } from "./my_plugin_base"; @@ -119,7 +118,7 @@ class CorePlugin extends MyPluginBase { 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.comment = storageUtils.getCommentStyleByLanguage(data.lang); data.percent = data.percent.toFixed(2); data.testcase = util.inspect(data.testcase || ""); diff --git a/src/childProcessCall/my_plugin_base.ts b/src/childProcessCall/my_plugin_base.ts index 1a0dd1a..c536d91 100644 --- a/src/childProcessCall/my_plugin_base.ts +++ b/src/childProcessCall/my_plugin_base.ts @@ -12,7 +12,7 @@ let underscore = require("underscore"); import { config as out_config } from "./config"; import { storageUtils } from "./storageUtils"; // import { log } from "./log"; -import { helper } from "./helper"; +import { commUtils } from "./commUtils"; export class MyPluginBase { id; @@ -31,12 +31,12 @@ export class MyPluginBase { constructor() {} public save() { - const stats = storageUtils.getCache(helper.KEYS.plugins) || {}; + const stats = storageUtils.getCache(commUtils.KEYS.plugins) || {}; if (this.deleted) delete stats[this.name]; else stats[this.name] = this.enabled; - storageUtils.setCache(helper.KEYS.plugins, stats); + storageUtils.setCache(commUtils.KEYS.plugins, stats); } public init() { @@ -46,7 +46,7 @@ export class MyPluginBase { public base_init(head?) { head = head || require("./core").corePlugin; - const stats = storageUtils.getCache(helper.KEYS.plugins) || {}; + const stats = storageUtils.getCache(commUtils.KEYS.plugins) || {}; let file_plugin: Array = storageUtils.listCodeDir("plugins"); this.installed = []; for (let f of file_plugin) { diff --git a/src/childProcessCall/plugins/cache.ts b/src/childProcessCall/plugins/cache.ts index 350217c..6bdd045 100644 --- a/src/childProcessCall/plugins/cache.ts +++ b/src/childProcessCall/plugins/cache.ts @@ -12,7 +12,7 @@ import { MyPluginBase } from "../my_plugin_base"; let underscore = require("underscore"); import { storageUtils } from "../storageUtils"; -import { helper } from "../helper"; +import { commUtils } from "../commUtils"; // import { log } from "../log"; import { session } from "../session"; @@ -25,13 +25,13 @@ class CachePlugin extends MyPluginBase { } clearCacheIfTchanged = (needTranslation) => { - const translationConfig = storageUtils.getCache(helper.KEYS.translation); + const translationConfig = storageUtils.getCache(commUtils.KEYS.translation); if ( !translationConfig || translationConfig["useEndpointTranslation"] != needTranslation ) { storageUtils.deleteAllCache(); - storageUtils.setCache(helper.KEYS.translation, { + storageUtils.setCache(commUtils.KEYS.translation, { useEndpointTranslation: needTranslation, }); } @@ -39,13 +39,13 @@ class CachePlugin extends MyPluginBase { public getProblems = (needTranslation, cb) => { this.clearCacheIfTchanged(needTranslation); - const problems = storageUtils.getCache(helper.KEYS.problems); + 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(helper.KEYS.problems, problems); + storageUtils.setCache(commUtils.KEYS.problems, problems); return cb(null, problems); }); }; @@ -54,7 +54,7 @@ class CachePlugin extends MyPluginBase { * getRatingOnline */ public getRatingOnline = (cb) => { - const cacheRantingData = storageUtils.getCache(helper.KEYS.ranting_path); + const cacheRantingData = storageUtils.getCache(commUtils.KEYS.ranting_path); if (cacheRantingData) { return cb(null, cacheRantingData); } @@ -66,14 +66,14 @@ class CachePlugin extends MyPluginBase { } catch (error) { return cb("JSON.parse(ratingData) error"); } - storageUtils.setCache(helper.KEYS.ranting_path, ratingObj); + storageUtils.setCache(commUtils.KEYS.ranting_path, ratingObj); return cb(null, ratingObj); }); }; public getProblem = (problem, needTranslation, cb) => { this.clearCacheIfTchanged(needTranslation); - const k = helper.KEYS.problem(problem); + const k = commUtils.KEYS.problem(problem); const _problem = storageUtils.getCache(k); let that = this; if (_problem) { @@ -96,18 +96,18 @@ class CachePlugin extends MyPluginBase { saveProblem = (problem) => { const _problem = underscore.omit(problem, ["locked", "state", "starred"]); - return storageUtils.setCache(helper.KEYS.problem(problem), _problem); + return storageUtils.setCache(commUtils.KEYS.problem(problem), _problem); }; updateProblem = (problem, kv) => { - const problems = storageUtils.getCache(helper.KEYS.problems); + 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(helper.KEYS.problems, problems); + return storageUtils.setCache(commUtils.KEYS.problems, problems); }; login = (user, cb) => { diff --git a/src/childProcessCall/plugins/leetcode.ts b/src/childProcessCall/plugins/leetcode.ts index 3853fa0..e31ad39 100644 --- a/src/childProcessCall/plugins/leetcode.ts +++ b/src/childProcessCall/plugins/leetcode.ts @@ -14,7 +14,7 @@ let request = require("request"); let prompt_out = require("prompt"); import { config } from "../config"; -import { helper } from "../helper"; +import { commUtils } from "../commUtils"; import { storageUtils } from "../storageUtils"; import { log } from "../log"; import { session } from "../session"; @@ -117,7 +117,7 @@ class LeetCode extends MyPluginBase { ), locked: p.paid_only, percent: (p.stat.total_acs * 100) / p.stat.total_submitted, - level: helper.levelToName(p.difficulty.level), + level: commUtils.levelToName(p.difficulty.level), starred: p.is_favor, category: json.category_slug, }; @@ -476,18 +476,11 @@ class LeetCode extends MyPluginBase { }; signin = (user, cb) => { - const isCN = config.app === "leetcode.cn"; - const spin = isCN - ? helper.spin("Signing in leetcode.cn") - : helper.spin("Signing in leetcode.com"); let that = this; request(config.sys.urls.login, function (e, resp, _) { - spin.stop(); 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, headers: { @@ -505,8 +498,8 @@ class LeetCode extends MyPluginBase { if (e) return cb(e); if (resp.statusCode !== 302) return cb("invalid password?"); - user.sessionCSRF = helper.getSetCookieValue(resp, "csrftoken"); - user.sessionId = helper.getSetCookieValue(resp, "LEETCODE_SESSION"); + user.sessionCSRF = commUtils.getSetCookieValue(resp, "csrftoken"); + user.sessionId = commUtils.getSetCookieValue(resp, "LEETCODE_SESSION"); session.saveUser(user); return cb(null, user); }); diff --git a/src/childProcessCall/session.ts b/src/childProcessCall/session.ts index 2999008..7fc3412 100644 --- a/src/childProcessCall/session.ts +++ b/src/childProcessCall/session.ts @@ -12,7 +12,7 @@ let underscore = require("underscore"); import { storageUtils } from "./storageUtils"; import { config } from "./config"; -import { helper } from "./helper"; +import { commUtils } from "./commUtils"; class Session { errors = { @@ -24,7 +24,7 @@ class Session { argv: any = {}; constructor() {} public getUser = function () { - return storageUtils.getCache(helper.KEYS.user); + return storageUtils.getCache(commUtils.KEYS.user); }; public saveUser = function (user) { @@ -34,15 +34,15 @@ class Session { user, config.autologin.enable ? [] : ["pass"] ); - storageUtils.setCache(helper.KEYS.user, _user); + 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() { @@ -52,7 +52,7 @@ class Session { 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 stats = storageUtils.getCache(commUtils.KEYS.stat) || {}; const stat = (stats[today] = stats[today] || {}); if (k.endsWith(".set")) { @@ -62,7 +62,7 @@ class Session { } 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(); diff --git a/src/childProcessCall/storageUtils.ts b/src/childProcessCall/storageUtils.ts index db4a1f0..f25e93e 100644 --- a/src/childProcessCall/storageUtils.ts +++ b/src/childProcessCall/storageUtils.ts @@ -28,6 +28,138 @@ export const defaultMETA: IMETA = { }; 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() { _.templateSettings = { evaluate: /\{\{(.+?)\}\}/g, @@ -221,19 +353,6 @@ class StorageUtils { 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 = diff --git a/src/controller/MainController.ts b/src/controller/MainController.ts index a3f5a0f..d8a0ddf 100644 --- a/src/controller/MainController.ts +++ b/src/controller/MainController.ts @@ -11,6 +11,7 @@ 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 { @@ -27,8 +28,20 @@ class MainContorller { } } + 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); } diff --git a/src/utils/CliUtils.ts b/src/utils/CliUtils.ts index 7577a54..2ad4cff 100644 --- a/src/utils/CliUtils.ts +++ b/src/utils/CliUtils.ts @@ -112,15 +112,20 @@ export async function executeCommandWithProgress( 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(); + const env: any = Object.create(process.env); if (proxy) { - const env: any = Object.create(process.env); env.http_proxy = proxy; return env; } - return process.env; + env.ccagml = childLCPTCTX(); + return env; } function getHttpAgent(): string | undefined { diff --git a/src/utils/OutputUtils.ts b/src/utils/OutputUtils.ts index 1790c69..38788ba 100644 --- a/src/utils/OutputUtils.ts +++ b/src/utils/OutputUtils.ts @@ -101,6 +101,7 @@ class LogOutput implements vscode.Disposable { private readonly channel: vscode.OutputChannel = vscode.window.createOutputChannel("LeetCodeProblemRating"); + private LCPTCTX = {}; public appendLine(message: string): void { this.channel.appendLine(message); } @@ -116,6 +117,18 @@ class LogOutput implements vscode.Disposable { 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(); From cb78127bbcc9aebe3bb9fceb80c46034dc800491 Mon Sep 17 00:00:00 2001 From: ccagml Date: Wed, 16 Nov 2022 19:19:00 +0800 Subject: [PATCH 03/26] update --- .eslintrc.js | 3 + src/childProcessCall/{log.ts => Reply.ts} | 10 +- src/childProcessCall/cli.ts | 4 +- src/childProcessCall/commands/cache.ts | 1 - src/childProcessCall/commands/config.ts | 96 -------- src/childProcessCall/commands/list.ts | 6 +- src/childProcessCall/commands/plugin.ts | 6 +- src/childProcessCall/commands/query.ts | 12 +- src/childProcessCall/commands/session.ts | 80 ------- src/childProcessCall/commands/show.ts | 48 ++-- src/childProcessCall/commands/star.ts | 8 +- src/childProcessCall/commands/stat.ts | 216 ------------------ src/childProcessCall/commands/submit.ts | 14 +- src/childProcessCall/commands/test.ts | 20 +- src/childProcessCall/commands/user.ts | 30 +-- src/childProcessCall/core.ts | 1 - src/childProcessCall/my_plugin_base.ts | 65 +++--- src/childProcessCall/plugins/cache.ts | 1 - src/childProcessCall/plugins/leetcode.ts | 8 +- .../plugins/solution.discuss.ts | 28 +-- 20 files changed, 133 insertions(+), 524 deletions(-) rename src/childProcessCall/{log.ts => Reply.ts} (80%) delete mode 100644 src/childProcessCall/commands/config.ts delete mode 100644 src/childProcessCall/commands/session.ts delete mode 100644 src/childProcessCall/commands/stat.ts diff --git a/.eslintrc.js b/.eslintrc.js index 8571aab..d310ceb 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -57,6 +57,9 @@ module.exports = { // 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"], }, // 如果有 js 和 ts 需要分开指定的规则,就 js 写 rules 里,ts 写 overrides 里 overrides: [ diff --git a/src/childProcessCall/log.ts b/src/childProcessCall/Reply.ts similarity index 80% rename from src/childProcessCall/log.ts rename to src/childProcessCall/Reply.ts index 2252412..ffcbcc3 100644 --- a/src/childProcessCall/log.ts +++ b/src/childProcessCall/Reply.ts @@ -1,7 +1,7 @@ /* - * 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 + * Filename: /home/cc/vscode-leetcode-problem-rating/src/childProcessCall/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. @@ -9,7 +9,7 @@ let _ = require("underscore"); -class LOG { +class Reply { output = _.bind(console.log, console); level; levels = new Map([ @@ -59,4 +59,4 @@ class LOG { } } -export const log: LOG = new LOG(); +export const reply: Reply = new Reply(); diff --git a/src/childProcessCall/cli.ts b/src/childProcessCall/cli.ts index 2ce1012..6af0798 100644 --- a/src/childProcessCall/cli.ts +++ b/src/childProcessCall/cli.ts @@ -9,7 +9,7 @@ import { myPluginBase } from "./my_plugin_base"; import { config } from "./config"; -import { log } from "./log"; +import { reply } from "./Reply"; import { storageUtils } from "./storageUtils"; class NewCli { constructor() { @@ -20,7 +20,7 @@ class NewCli { if (e.code === "EPIPE") process.exit(); }); config.init(JSON.parse(process.env.ccagml || "{}")); - log.init(); + reply.init(); storageUtils.init(); if (myPluginBase.base_init()) { myPluginBase.save(); diff --git a/src/childProcessCall/commands/cache.ts b/src/childProcessCall/commands/cache.ts index 044723c..4af66a5 100644 --- a/src/childProcessCall/commands/cache.ts +++ b/src/childProcessCall/commands/cache.ts @@ -10,7 +10,6 @@ // let underscore = require('underscore'); import { commUtils } from "../commUtils"; -// import { log } from "../log"; import { storageUtils } from "../storageUtils"; import { session } from "../session"; diff --git a/src/childProcessCall/commands/config.ts b/src/childProcessCall/commands/config.ts deleted file mode 100644 index 11251d9..0000000 --- a/src/childProcessCall/commands/config.ts +++ /dev/null @@ -1,96 +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 { commUtils } from "../commUtils"; - -class ConfigCommand { - constructor() {} - - // process_argv(argv) { - // let argv_config = commUtils.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 index 552a38c..4dcd2e3 100644 --- a/src/childProcessCall/commands/list.ts +++ b/src/childProcessCall/commands/list.ts @@ -8,7 +8,7 @@ */ import { commUtils } from "../commUtils"; -import { log } from "../log"; +import { reply } from "../Reply"; import { corePlugin } from "../core"; import { session } from "../session"; @@ -52,7 +52,7 @@ class ListCommand { handler(argv) { session.argv = argv; corePlugin.filterProblems(argv, function (e, problems) { - if (e) return log.info(e); + if (e) return reply.info(e); let new_objcet: Array = []; problems.forEach((element) => { let temp_ele: any = {}; @@ -63,7 +63,7 @@ class ListCommand { } new_objcet.push(temp_ele); }); - log.info(JSON.stringify(new_objcet)); + reply.info(JSON.stringify(new_objcet)); }); } } diff --git a/src/childProcessCall/commands/plugin.ts b/src/childProcessCall/commands/plugin.ts index 0634b6a..75945a1 100644 --- a/src/childProcessCall/commands/plugin.ts +++ b/src/childProcessCall/commands/plugin.ts @@ -9,7 +9,7 @@ import { commUtils } from "../commUtils"; import { config } from "../config"; -import { log } from "../log"; +import { reply } from "../Reply"; import { myPluginBase } from "../my_plugin_base"; import { session } from "../session"; @@ -69,7 +69,7 @@ class PluginCommand { all_plugin = all_plugin.filter((x) => x.name === name); } if (all_plugin.length === 0) { - return log.fatal("Plugin not found!"); + return reply.fatal("Plugin not found!"); } const p = all_plugin[0]; @@ -84,7 +84,7 @@ class PluginCommand { p.save(); myPluginBase.init(); } else if (argv.config) { - log.info(JSON.stringify(config.plugins[name] || {}, null, 2)); + reply.info(JSON.stringify(config.plugins[name] || {}, null, 2)); } }; } diff --git a/src/childProcessCall/commands/query.ts b/src/childProcessCall/commands/query.ts index a501d11..3996cdd 100644 --- a/src/childProcessCall/commands/query.ts +++ b/src/childProcessCall/commands/query.ts @@ -8,7 +8,7 @@ */ import { commUtils } from "../commUtils"; -import { log } from "../log"; +import { reply } from "../Reply"; import { corePlugin } from "../core"; import { session } from "../session"; @@ -56,12 +56,12 @@ class QueryCommand { if (argv.a) { corePlugin.getTodayQuestion(function (e, result) { if (e) return; - log.info(JSON.stringify(result)); + reply.info(JSON.stringify(result)); }); } else if (argv.b) { corePlugin.getUserContest(argv.b, function (e, result) { if (e) return; - log.info(JSON.stringify(result)); + reply.info(JSON.stringify(result)); }); } else if (argv.c) { corePlugin.getRating(function (e, result) { @@ -70,19 +70,19 @@ class QueryCommand { code: 101, data: {}, }; - log.info(JSON.stringify(log_data)); + reply.info(JSON.stringify(log_data)); return; } let log_data = { code: 100, data: result, }; - log.info(JSON.stringify(log_data)); + reply.info(JSON.stringify(log_data)); }); } else if (argv.z) { corePlugin.getQueryZ(argv.z, function (e, result) { if (e) return; - log.info(JSON.stringify(result)); + reply.info(JSON.stringify(result)); }); } }; diff --git a/src/childProcessCall/commands/session.ts b/src/childProcessCall/commands/session.ts deleted file mode 100644 index 11f2258..0000000 --- a/src/childProcessCall/commands/session.ts +++ /dev/null @@ -1,80 +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 { commUtils } from "../commUtils"; -// 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 ? commUtils.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 index 032d04f..baefa95 100644 --- a/src/childProcessCall/commands/show.ts +++ b/src/childProcessCall/commands/show.ts @@ -13,7 +13,7 @@ let childProcess = require("child_process"); import { commUtils } from "../commUtils"; import { storageUtils } from "../storageUtils"; -import { log } from "../log"; +import { reply } from "../Reply"; import { config } from "../config"; import { corePlugin } from "../core"; import { session } from "../session"; @@ -111,8 +111,8 @@ class ShowCommand { 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); + reply.info('Not supported language "' + argv.lang + '"'); + reply.warn("Supported languages: " + langlist); return; } @@ -138,43 +138,43 @@ class ShowCommand { } } else { if (argv.codeonly) { - log.info(code); + reply.info(code); return; } } - log.info(`[${problem.fid}] ${problem.name}`); - log.info(); - log.info(problem.link); + reply.info(`[${problem.fid}] ${problem.name}`); + reply.info(); + reply.info(problem.link); if (argv.extra) { - log.info(); - log.info("Tags: " + taglist); - log.info(); - log.info("Langs: " + langlist); + reply.info(); + reply.info("Tags: " + taglist); + reply.info(); + reply.info("Langs: " + langlist); } - log.info(); - log.info(`* ${problem.category}`); - log.info( + reply.info(); + reply.info(`* ${problem.category}`); + reply.info( `* ${commUtils.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.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) - log.info(`* Total Submissions: ${problem.totalSubmit}`); + reply.info(`* Total Submissions: ${problem.totalSubmit}`); if (problem.testable && problem.testcase) { let testcase_value = util.inspect(problem.testcase); - log.info(`* Testcase Example: ${testcase_value}`); + reply.info(`* Testcase Example: ${testcase_value}`); } - if (filename) log.info(`* Source Code: ${filename}`); + if (filename) reply.info(`* Source Code: ${filename}`); - log.info(); - log.info(problem.desc); + reply.info(); + reply.info(problem.desc); } handler(argv) { @@ -186,7 +186,7 @@ class ShowCommand { argv.keyword, !argv.dontTranslate, function (e, problem) { - if (e) return log.info(e); + if (e) return reply.info(e); that.showProblem(problem, argv); } ); diff --git a/src/childProcessCall/commands/star.ts b/src/childProcessCall/commands/star.ts index 99c164f..fec2272 100644 --- a/src/childProcessCall/commands/star.ts +++ b/src/childProcessCall/commands/star.ts @@ -8,7 +8,7 @@ */ import { commUtils } from "../commUtils"; -import { log } from "../log"; +import { reply } from "../Reply"; import { corePlugin } from "../core"; import { session } from "../session"; @@ -39,11 +39,11 @@ class StarCommand { session.argv = argv; // translation doesn't affect question lookup corePlugin.getProblem(argv.keyword, true, function (e, problem) { - if (e) return log.info(e); + if (e) return reply.info(e); corePlugin.starProblem(problem, !argv.delete, function (e, starred) { - if (e) return log.info(e); - log.info( + if (e) return reply.info(e); + reply.info( `[${problem.fid}] ${problem.name} ${ starred ? "icon.like" : "icon.unlike" }` diff --git a/src/childProcessCall/commands/stat.ts b/src/childProcessCall/commands/stat.ts deleted file mode 100644 index 949f242..0000000 --- a/src/childProcessCall/commands/stat.ts +++ /dev/null @@ -1,216 +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 { commUtils } from "../commUtils"; -// import { log } from "../log"; -// import { corePlugin } from "../core"; -// import { session } from "../session"; - -class StatCommand { - constructor() {} - - // process_argv(argv) { - // let argv_config = commUtils.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', - // commUtils.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(commUtils.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 index 0a596b7..b8d2eda 100644 --- a/src/childProcessCall/commands/submit.ts +++ b/src/childProcessCall/commands/submit.ts @@ -12,7 +12,7 @@ let lodash = require("lodash"); import { commUtils } from "../commUtils"; import { storageUtils } from "../storageUtils"; -import { log } from "../log"; +import { reply } from "../Reply"; import { corePlugin } from "../core"; import { session } from "../session"; @@ -57,19 +57,19 @@ class SubmitCommand { handler(argv) { session.argv = argv; if (!storageUtils.exist(argv.filename)) - return log.fatal("File " + argv.filename + " not exist!"); + return reply.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); + if (e) return reply.info(e); problem.file = argv.filename; problem.lang = meta.lang; corePlugin.submitProblem(problem, function (e, results) { - if (e) return log.info(e); + if (e) return reply.info(e); const result = results[0]; @@ -106,7 +106,7 @@ class SubmitCommand { result.runtime_percentile.toFixed(2), result.lang ); - else return log.warn("Failed to get runtime percentile."); + else return reply.warn("Failed to get runtime percentile."); if (result.memory && result.memory_percentile) that.printLine( log_obj, @@ -116,7 +116,7 @@ class SubmitCommand { result.lang, result.memory ); - else return log.warn("Failed to get memory percentile."); + else return reply.warn("Failed to get memory percentile."); })(); } else { result.testcase = result.testcase.slice(1, -1).replace(/\\n/g, "\n"); @@ -126,7 +126,7 @@ class SubmitCommand { that.printResult(result, "expected_answer", log_obj); that.printResult(result, "stdout", log_obj); } - log.info(JSON.stringify(log_obj)); + reply.info(JSON.stringify(log_obj)); corePlugin.updateProblem(problem, { state: result.ok ? "ac" : "notac", }); diff --git a/src/childProcessCall/commands/test.ts b/src/childProcessCall/commands/test.ts index 1f61e0a..0d97195 100644 --- a/src/childProcessCall/commands/test.ts +++ b/src/childProcessCall/commands/test.ts @@ -12,7 +12,7 @@ let lodash = require("lodash"); import { commUtils } from "../commUtils"; import { storageUtils } from "../storageUtils"; -import { log } from "../log"; +import { reply } from "../Reply"; import { corePlugin } from "../core"; import { session } from "../session"; @@ -78,7 +78,7 @@ class TestCommand { runTest(argv) { let that = this; if (!storageUtils.exist(argv.filename)) - return log.fatal("File " + argv.filename + " not exist!"); + return reply.fatal("File " + argv.filename + " not exist!"); const meta = storageUtils.meta(argv.filename); @@ -87,7 +87,7 @@ class TestCommand { corePlugin.getProblem(meta, true, function (e, problem) { if (e) - return log.info( + return reply.info( JSON.stringify({ messages: ["error"], code: [-1], @@ -96,7 +96,7 @@ class TestCommand { ); if (!problem.testable) - return log.info( + return reply.info( JSON.stringify({ messages: ["error"], code: [-2], @@ -123,7 +123,7 @@ class TestCommand { let temp_collect = ""; for (let all_input = 0; all_input < input.length; all_input++) { const element = input[all_input]; - var check_index = element.indexOf("输入"); + let check_index = element.indexOf("输入"); if (check_index == -1) { check_index = element.indexOf("Input:"); } @@ -133,7 +133,7 @@ class TestCommand { continue; } - var check_index = element.indexOf("输出"); + check_index = element.indexOf("输出"); if (check_index == -1) { check_index = element.indexOf("Output:"); } @@ -179,7 +179,7 @@ class TestCommand { } if (!problem.testcase) - return log.info( + return reply.info( JSON.stringify({ messages: ["error"], code: [-3], @@ -191,7 +191,7 @@ class TestCommand { problem.lang = meta.lang; corePlugin.testProblem(problem, function (e, results) { - if (e) return log.info(JSON.stringify(e)); + if (e) return reply.info(JSON.stringify(e)); results = _.sortBy(results, (x) => x.type); @@ -224,7 +224,7 @@ class TestCommand { 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)); + reply.info(JSON.stringify(log_obj)); }); }); } @@ -235,7 +235,7 @@ class TestCommand { if (!argv.i) return that.runTest(argv); commUtils.readStdin(function (e, data) { - if (e) return log.info(e); + if (e) return reply.info(e); argv.testcase = data; return that.runTest(argv); diff --git a/src/childProcessCall/commands/user.ts b/src/childProcessCall/commands/user.ts index 3a6e2ea..8f114e2 100644 --- a/src/childProcessCall/commands/user.ts +++ b/src/childProcessCall/commands/user.ts @@ -9,7 +9,7 @@ let prompt_out = require("prompt"); import { commUtils } from "../commUtils"; -import { log } from "../log"; +import { reply } from "../Reply"; import { corePlugin } from "../core"; import { session } from "../session"; @@ -70,23 +70,23 @@ class UserCommand { ], function (e, user) { if (e) { - return log.info(JSON.stringify({ code: -1, msg: e.msg || e })); + return reply.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 })); + return reply.info(JSON.stringify({ code: -2, msg: e.msg || e })); } - log.info(JSON.stringify({ code: 100, user_name: user.name })); + reply.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 })); + if (user) reply.info(JSON.stringify({ code: 100, user_name: user.name })); else - log.info(JSON.stringify({ code: -3, msg: "You are not login yet?" })); + 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 @@ -109,11 +109,13 @@ class UserCommand { ], function (e, user) { if (e) - return log.info(JSON.stringify({ code: -4, msg: e.msg || e })); + return reply.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 })); + return reply.info( + JSON.stringify({ code: -5, msg: e.msg || e }) + ); + reply.info(JSON.stringify({ code: 100, user_name: user.name })); }); } ); @@ -129,11 +131,11 @@ class UserCommand { { name: "cookie", required: true }, ], function (e, user) { - if (e) return log.info(e); + if (e) return reply.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 })); + return reply.info(JSON.stringify({ code: -6, msg: e.msg || e })); + reply.info(JSON.stringify({ code: 100, user_name: user.name })); }); } ); @@ -141,9 +143,9 @@ class UserCommand { // show current user user = session.getUser(); if (user) { - log.info(JSON.stringify({ code: 100, user_name: user.name })); + reply.info(JSON.stringify({ code: 100, user_name: user.name })); } else - return log.info( + return reply.info( JSON.stringify({ code: -7, msg: "You are not login yet?" }) ); } diff --git a/src/childProcessCall/core.ts b/src/childProcessCall/core.ts index 660c2c6..4907876 100644 --- a/src/childProcessCall/core.ts +++ b/src/childProcessCall/core.ts @@ -12,7 +12,6 @@ let util = require("util"); let _ = require("underscore"); let cheerio = require("cheerio"); -// import { log } from "./log"; import { storageUtils } from "./storageUtils"; import { MyPluginBase } from "./my_plugin_base"; diff --git a/src/childProcessCall/my_plugin_base.ts b/src/childProcessCall/my_plugin_base.ts index c536d91..6140976 100644 --- a/src/childProcessCall/my_plugin_base.ts +++ b/src/childProcessCall/my_plugin_base.ts @@ -11,7 +11,6 @@ let underscore = require("underscore"); import { config as out_config } from "./config"; import { storageUtils } from "./storageUtils"; -// import { log } from "./log"; import { commUtils } from "./commUtils"; export class MyPluginBase { @@ -30,7 +29,7 @@ export class MyPluginBase { config; constructor() {} - public save() { + public save(): void { const stats = storageUtils.getCache(commUtils.KEYS.plugins) || {}; if (this.deleted) delete stats[this.name]; @@ -39,12 +38,12 @@ export class MyPluginBase { storageUtils.setCache(commUtils.KEYS.plugins, stats); } - public init() { + public init(): void { this.config = out_config.plugins[this.name] || {}; this.next = null; } - public base_init(head?) { + public base_init(head?): Object { head = head || require("./core").corePlugin; const stats = storageUtils.getCache(commUtils.KEYS.plugins) || {}; let file_plugin: Array = storageUtils.listCodeDir("plugins"); @@ -82,102 +81,102 @@ export class MyPluginBase { return true; } - public setNext(next) { + public setNext(next): void { Object.setPrototypeOf(this, next); this.next = next; } - public save_all() { + public save_all(): void { for (let p of this.plugins) { p.save(); } } - public getProblems(Translate: boolean, cb) { + public getProblems(Translate: boolean, cb: Function): void { this.next.getProblems(Translate, cb); } - public getQuestionOfToday(cb) { + public getQuestionOfToday(cb: Function): void { this.next.getQuestionOfToday(cb); } - public getRatingOnline(cb) { + public getRatingOnline(cb: Function): void { this.next.getRatingOnline(cb); } - public getTestApi(username, cb) { + public getTestApi(username, cb: Function): void { this.next.getTestApi(username, cb); } - public getUserContestP(username, cb) { + public getUserContestP(username, cb: Function): void { this.next.getUserContestP(username, cb); } - public getProblemsTitle(cb) { + public getProblemsTitle(cb: Function): void { this.next.getProblemsTitle(cb); } - public createSession(a, cb) { + public createSession(a, cb: Function): void { this.next.createSession(a, cb); } - public getSessions(cb) { + public getSessions(cb: Function): void { this.next.getSessions(cb); } - public activateSession(s, cb) { + public activateSession(s, cb: Function): void { this.next.activateSession(s, cb); } - public deleteSession(s, cb) { + public deleteSession(s, cb: Function): void { this.next.deleteSession(s, cb); } - public updateProblem(a, b) { + public updateProblem(a, b): void { this.next.updateProblem(a, b); } - public getSubmissions(s, cb) { + public getSubmissions(s, cb: Function): void { this.next.getSubmissions(s, cb); } - public getSubmission(s, cb) { + public getSubmission(s, cb: Function): void { this.next.getSubmission(s, cb); } - public submitProblem(s, cb) { + public submitProblem(s, cb: Function): void { this.next.submitProblem(s, cb); } - public testProblem(s, cb) { + public testProblem(s, cb: Function): void { this.next.testProblem(s, cb); } - public login(user, cb) { + public login(user, cb: Function): void { this.next.login(user, cb); } - public logout(user, cb) { + public logout(user, cb): void { this.next.logout(user, cb); } - public githubLogin(user, cb) { + public githubLogin(user, cb: Function): void { this.next.githubLogin(user, cb); } - public linkedinLogin(user, cb) { + public linkedinLogin(user, cb: Function): void { this.next.linkedinLogin(user, cb); } - public cookieLogin(user, cb) { + public cookieLogin(user, cb: Function): void { this.next.cookieLogin(user, cb); } - public filterProblems(opts, cb) { + public filterProblems(opts, cb: Function): void { this.next.filterProblems(opts, cb); } - public getProblem(keyword, needTranslation, cb) { + public getProblem(keyword, needTranslation, cb: Function): void { this.next.getProblem(keyword, needTranslation, cb); } - public starProblem(problem, starred, cb) { + public starProblem(problem, starred, cb: Function): void { this.next.starProblem(problem, starred, cb); } - public exportProblem(problem, opts) { + public exportProblem(problem, opts): void { this.next.exportProblem(problem, opts); } - public getTodayQuestion(cb) { + public getTodayQuestion(cb: Function): void { this.next.getTodayQuestion(cb); } - public getQueryZ(username, cb) { + public getQueryZ(username, cb: Function): void { this.next.getQueryZ(username, cb); } - public getUserContest(username, cb) { + public getUserContest(username, cb: Function): void { this.next.getUserContest(username, cb); } } diff --git a/src/childProcessCall/plugins/cache.ts b/src/childProcessCall/plugins/cache.ts index 6bdd045..faa19ed 100644 --- a/src/childProcessCall/plugins/cache.ts +++ b/src/childProcessCall/plugins/cache.ts @@ -13,7 +13,6 @@ let underscore = require("underscore"); import { storageUtils } from "../storageUtils"; import { commUtils } from "../commUtils"; -// import { log } from "../log"; import { session } from "../session"; class CachePlugin extends MyPluginBase { diff --git a/src/childProcessCall/plugins/leetcode.ts b/src/childProcessCall/plugins/leetcode.ts index e31ad39..dab3e5f 100644 --- a/src/childProcessCall/plugins/leetcode.ts +++ b/src/childProcessCall/plugins/leetcode.ts @@ -16,7 +16,7 @@ let prompt_out = require("prompt"); import { config } from "../config"; import { commUtils } from "../commUtils"; import { storageUtils } from "../storageUtils"; -import { log } from "../log"; +import { reply } from "../Reply"; import { session } from "../session"; import { MyPluginBase } from "../my_plugin_base"; import { Queue } from "../queue"; @@ -517,10 +517,10 @@ class LeetCode extends MyPluginBase { 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) { @@ -643,7 +643,7 @@ class LeetCode extends MyPluginBase { }, ], function (e, result) { - if (e) return log.info(e); + if (e) return reply.info(e); const authenticityTokenTwoFactor = body.match( /name="authenticity_token" value="(.*?)"/ ); diff --git a/src/childProcessCall/plugins/solution.discuss.ts b/src/childProcessCall/plugins/solution.discuss.ts index 7b439d8..c533e61 100644 --- a/src/childProcessCall/plugins/solution.discuss.ts +++ b/src/childProcessCall/plugins/solution.discuss.ts @@ -9,7 +9,7 @@ let request = require("request"); -import { log } from "../log"; +import { reply } from "../Reply"; import { session } from "../session"; import { MyPluginBase } from "../my_plugin_base"; @@ -28,7 +28,7 @@ class SolutionDiscuss extends MyPluginBase { 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); + if (!solution) return reply.error("Solution not found for " + lang); let link = URL_DISCUSS.replace("$slug", problem.slug).replace( "$id", @@ -38,18 +38,18 @@ class SolutionDiscuss extends MyPluginBase { .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); + 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); }); }); }; From 18d0c5eefe4f1904e82bee5de770b6d2383156e4 Mon Sep 17 00:00:00 2001 From: ccagml Date: Thu, 17 Nov 2022 10:46:31 +0800 Subject: [PATCH 04/26] update --- CHANGELOG.md | 5 + package-lock.json | 4 +- package.json | 2 +- .../chain.ts} | 29 ++-- .../chainNode}/cache.ts | 16 +-- .../{ => actionChain/chainNode}/core.ts | 36 +---- .../chainNode}/leetcode.cn.ts | 26 ++-- .../chainNode}/leetcode.ts | 22 ++-- .../chainNode}/retry.ts | 14 +- .../chainNode}/solution.discuss.ts | 14 +- src/childProcessCall/cli.ts | 19 ++- src/childProcessCall/commUtils.ts | 75 ----------- src/childProcessCall/commands/cache.ts | 52 -------- src/childProcessCall/commands/list.ts | 71 ---------- src/childProcessCall/commands/star.ts | 57 -------- src/childProcessCall/factory/api/cache.ts | 52 ++++++++ src/childProcessCall/factory/api/list.ts | 91 +++++++++++++ .../{commands => factory/api}/plugin.ts | 43 +++--- .../{commands => factory/api}/query.ts | 44 ++++--- .../{commands => factory/api}/show.ts | 74 +++++++---- src/childProcessCall/factory/api/star.ts | 61 +++++++++ .../{commands => factory/api}/submission.ts | 12 +- .../{commands => factory/api}/submit.ts | 39 +++--- .../{commands => factory/api}/test.ts | 39 +++--- .../{commands => factory/api}/user.ts | 48 +++---- src/childProcessCall/factory/apiFactory.ts | 124 ++++++++++++++++++ 26 files changed, 584 insertions(+), 485 deletions(-) rename src/childProcessCall/{my_plugin_base.ts => actionChain/chain.ts} (87%) rename src/childProcessCall/{plugins => actionChain/chainNode}/cache.ts (88%) rename src/childProcessCall/{ => actionChain/chainNode}/core.ts (82%) rename src/childProcessCall/{plugins => actionChain/chainNode}/leetcode.cn.ts (90%) rename src/childProcessCall/{plugins => actionChain/chainNode}/leetcode.ts (97%) rename src/childProcessCall/{plugins => actionChain/chainNode}/retry.ts (82%) rename src/childProcessCall/{plugins => actionChain/chainNode}/solution.discuss.ts (87%) delete mode 100644 src/childProcessCall/commands/cache.ts delete mode 100644 src/childProcessCall/commands/list.ts delete mode 100644 src/childProcessCall/commands/star.ts create mode 100644 src/childProcessCall/factory/api/cache.ts create mode 100644 src/childProcessCall/factory/api/list.ts rename src/childProcessCall/{commands => factory/api}/plugin.ts (63%) rename src/childProcessCall/{commands => factory/api}/query.ts (63%) rename src/childProcessCall/{commands => factory/api}/show.ts (74%) create mode 100644 src/childProcessCall/factory/api/star.ts rename src/childProcessCall/{commands => factory/api}/submission.ts (92%) rename src/childProcessCall/{commands => factory/api}/submit.ts (79%) rename src/childProcessCall/{commands => factory/api}/test.ts (88%) rename src/childProcessCall/{commands => factory/api}/user.ts (78%) create mode 100644 src/childProcessCall/factory/apiFactory.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 2b2ffb0..b1c1fb8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +## version 2.0.1 + +- 重构工厂模式、责任链模式 +- 去除多余模块 + ## version 2.0.0 - 重构 diff --git a/package-lock.json b/package-lock.json index 75f20cb..e8f44b6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "vscode-leetcode-problem-rating", - "version": "2.0.0", + "version": "2.0.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "vscode-leetcode-problem-rating", - "version": "2.0.0", + "version": "2.0.1", "license": "MIT", "dependencies": { "ansi-styles": "3.2.1", diff --git a/package.json b/package.json index 1d13194..d6b30dd 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.0.1", "author": "ccagml", "publisher": "ccagml", "license": "MIT", diff --git a/src/childProcessCall/my_plugin_base.ts b/src/childProcessCall/actionChain/chain.ts similarity index 87% rename from src/childProcessCall/my_plugin_base.ts rename to src/childProcessCall/actionChain/chain.ts index 6140976..6cfca26 100644 --- a/src/childProcessCall/my_plugin_base.ts +++ b/src/childProcessCall/actionChain/chain.ts @@ -1,7 +1,7 @@ /* - * 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 + * Filename: /home/cc/vscode-leetcode-problem-rating/src/childProcessCall/actionChain/chain.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. @@ -9,11 +9,11 @@ let underscore = require("underscore"); -import { config as out_config } from "./config"; -import { storageUtils } from "./storageUtils"; -import { commUtils } from "./commUtils"; +import { config as out_config } from "../config"; +import { storageUtils } from "../storageUtils"; +import { commUtils } from "../commUtils"; -export class MyPluginBase { +export class Chain { id; name; ver; @@ -24,7 +24,7 @@ export class MyPluginBase { deps; next; plugins: Array = []; - installed: Array = []; + installed: Array = []; head; // 插件头 是core config; constructor() {} @@ -43,8 +43,12 @@ export class MyPluginBase { this.next = null; } - public base_init(head?): Object { - head = head || require("./core").corePlugin; + public getChainHead(): Chain { + return this.head; + } + + public base_init(head): Object { + this.head = head; const stats = storageUtils.getCache(commUtils.KEYS.plugins) || {}; let file_plugin: Array = storageUtils.listCodeDir("plugins"); this.installed = []; @@ -179,6 +183,9 @@ export class MyPluginBase { public getUserContest(username, cb: Function): void { this.next.getUserContest(username, cb); } + public getRating(cb: Function): void { + this.next.getRating(cb); + } } -export const myPluginBase: MyPluginBase = new MyPluginBase(); +export const chain: Chain = new Chain(); diff --git a/src/childProcessCall/plugins/cache.ts b/src/childProcessCall/actionChain/chainNode/cache.ts similarity index 88% rename from src/childProcessCall/plugins/cache.ts rename to src/childProcessCall/actionChain/chainNode/cache.ts index faa19ed..562f2a8 100644 --- a/src/childProcessCall/plugins/cache.ts +++ b/src/childProcessCall/actionChain/chainNode/cache.ts @@ -1,21 +1,21 @@ /* - * 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 + * Filename: /home/cc/vscode-leetcode-problem-rating/src/childProcessCall/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 { MyPluginBase } from "../my_plugin_base"; +import { Chain } from "../chain"; let underscore = require("underscore"); -import { storageUtils } from "../storageUtils"; -import { commUtils } from "../commUtils"; -import { session } from "../session"; +import { storageUtils } from "../../storageUtils"; +import { commUtils } from "../../commUtils"; +import { session } from "../../session"; -class CachePlugin extends MyPluginBase { +class CachePlugin extends Chain { id = 50; name = "cache"; builtin = true; diff --git a/src/childProcessCall/core.ts b/src/childProcessCall/actionChain/chainNode/core.ts similarity index 82% rename from src/childProcessCall/core.ts rename to src/childProcessCall/actionChain/chainNode/core.ts index 4907876..48dbbb9 100644 --- a/src/childProcessCall/core.ts +++ b/src/childProcessCall/actionChain/chainNode/core.ts @@ -1,7 +1,7 @@ /* - * 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/childProcessCall/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. @@ -12,42 +12,18 @@ let util = require("util"); let _ = require("underscore"); let cheerio = require("cheerio"); -import { storageUtils } from "./storageUtils"; +import { storageUtils } from "../../storageUtils"; -import { MyPluginBase } from "./my_plugin_base"; +import { Chain } from "../chain"; function hasTag(o, tag) { return Array.isArray(o) && o.some((x) => x.indexOf(tag.toLowerCase()) >= 0); } -class CorePlugin extends MyPluginBase { +class CorePlugin extends Chain { id = 99999999; 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(); } diff --git a/src/childProcessCall/plugins/leetcode.cn.ts b/src/childProcessCall/actionChain/chainNode/leetcode.cn.ts similarity index 90% rename from src/childProcessCall/plugins/leetcode.cn.ts rename to src/childProcessCall/actionChain/chainNode/leetcode.cn.ts index 3c166a6..7b52d79 100644 --- a/src/childProcessCall/plugins/leetcode.cn.ts +++ b/src/childProcessCall/actionChain/chainNode/leetcode.cn.ts @@ -1,21 +1,21 @@ /* - * 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/childProcessCall/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 { MyPluginBase } from "../my_plugin_base"; +import { Chain } from "./../chain"; let request = require("request"); -import { config } from "../config"; +import { config } from "../../config"; -import { session } from "../session"; +import { session } from "../../session"; -class LeetCodeCn extends MyPluginBase { +class LeetCodeCn extends Chain { id = 15; name = "leetcode.cn"; builtin = true; @@ -180,7 +180,7 @@ class LeetCodeCn extends MyPluginBase { const _request = request.defaults({ jar: true }); _request( "https://zerotrac.github.io/leetcode_problem_rating/data.json", - function (error, _, body) { + function (error: any, _, body: any) { // console.log(error); // console.log(info); cb(error, body); @@ -188,11 +188,11 @@ class LeetCodeCn extends MyPluginBase { ); }; - getTestApi = (value, _) => { + getTestApi = (value: any, _) => { const _request = request.defaults({ jar: true }); _request( "https://zerotrac.github.io/leetcode_problem_rating/data.json", - function (error, info, body) { + function (error: any, info: any, body: any) { console.log(error); console.log(info); let a = body; @@ -202,7 +202,7 @@ class LeetCodeCn extends MyPluginBase { }; } -function signOpts(opts, user) { +function signOpts(opts: any, user: any) { opts.headers.Cookie = "LEETCODE_SESSION=" + user.sessionId + @@ -213,7 +213,7 @@ function signOpts(opts, user) { opts.headers["X-Requested-With"] = "XMLHttpRequest"; } -function makeOpts(url) { +function makeOpts(url: any) { let opts: any = {}; opts.url = url; opts.headers = {}; @@ -222,7 +222,7 @@ function makeOpts(url) { 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; diff --git a/src/childProcessCall/plugins/leetcode.ts b/src/childProcessCall/actionChain/chainNode/leetcode.ts similarity index 97% rename from src/childProcessCall/plugins/leetcode.ts rename to src/childProcessCall/actionChain/chainNode/leetcode.ts index dab3e5f..0c804e8 100644 --- a/src/childProcessCall/plugins/leetcode.ts +++ b/src/childProcessCall/actionChain/chainNode/leetcode.ts @@ -1,7 +1,7 @@ /* - * 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/childProcessCall/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. @@ -13,15 +13,15 @@ let underscore = require("underscore"); let request = require("request"); let prompt_out = require("prompt"); -import { config } from "../config"; -import { commUtils } from "../commUtils"; -import { storageUtils } from "../storageUtils"; -import { reply } from "../Reply"; -import { session } from "../session"; -import { MyPluginBase } from "../my_plugin_base"; -import { Queue } from "../queue"; +import { config } from "../../config"; +import { commUtils } from "../../commUtils"; +import { storageUtils } from "../../storageUtils"; +import { reply } from "../../Reply"; +import { session } from "../../session"; +import { Chain } from "./../chain"; +import { Queue } from "../../queue"; -class LeetCode extends MyPluginBase { +class LeetCode extends Chain { id = 10; name = "leetcode"; builtin = true; diff --git a/src/childProcessCall/plugins/retry.ts b/src/childProcessCall/actionChain/chainNode/retry.ts similarity index 82% rename from src/childProcessCall/plugins/retry.ts rename to src/childProcessCall/actionChain/chainNode/retry.ts index aba1696..b201e49 100644 --- a/src/childProcessCall/plugins/retry.ts +++ b/src/childProcessCall/actionChain/chainNode/retry.ts @@ -1,17 +1,17 @@ /* - * 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/childProcessCall/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 { MyPluginBase } from "../my_plugin_base"; -import { config } from "../config"; -import { session } from "../session"; +import { Chain } from "./../chain"; +import { config } from "../../config"; +import { session } from "../../session"; -class RetryPlugin extends MyPluginBase { +class RetryPlugin extends Chain { id = 30; name = "retry"; builtin = true; diff --git a/src/childProcessCall/plugins/solution.discuss.ts b/src/childProcessCall/actionChain/chainNode/solution.discuss.ts similarity index 87% rename from src/childProcessCall/plugins/solution.discuss.ts rename to src/childProcessCall/actionChain/chainNode/solution.discuss.ts index c533e61..db56367 100644 --- a/src/childProcessCall/plugins/solution.discuss.ts +++ b/src/childProcessCall/actionChain/chainNode/solution.discuss.ts @@ -1,7 +1,7 @@ /* - * 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 + * Filename: /home/cc/vscode-leetcode-problem-rating/src/childProcessCall/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. @@ -9,11 +9,11 @@ let request = require("request"); -import { reply } from "../Reply"; -import { session } from "../session"; -import { MyPluginBase } from "../my_plugin_base"; +import { reply } from "../../Reply"; +import { session } from "../../session"; +import { Chain } from "./../chain"; -class SolutionDiscuss extends MyPluginBase { +class SolutionDiscuss extends Chain { id = 200; name = "solution.discuss"; builtin = true; diff --git a/src/childProcessCall/cli.ts b/src/childProcessCall/cli.ts index 6af0798..08bc167 100644 --- a/src/childProcessCall/cli.ts +++ b/src/childProcessCall/cli.ts @@ -7,10 +7,13 @@ * Copyright (c) 2022 ccagml . All rights reserved. */ -import { myPluginBase } from "./my_plugin_base"; +import { chain } from "./actionChain/chain"; +import { corePlugin } from "./actionChain/chainNode/core"; import { config } from "./config"; import { reply } from "./Reply"; import { storageUtils } from "./storageUtils"; +import { IApi, apiFactory } from "./factory/apiFactory"; + class NewCli { constructor() { this.run(); @@ -22,16 +25,18 @@ class NewCli { config.init(JSON.parse(process.env.ccagml || "{}")); reply.init(); storageUtils.init(); - if (myPluginBase.base_init()) { - myPluginBase.save(); + if (chain.base_init(corePlugin)) { + chain.save(); storageUtils.initCache(); - this.runCommand_new(); + this.doApi(); } } - private runCommand_new() { + private doApi() { 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)); + let curApi: IApi | undefined = apiFactory.getApi(com_str); + if (curApi != undefined) { + curApi.call(curApi.callArg(process.argv)); + } } } diff --git a/src/childProcessCall/commUtils.ts b/src/childProcessCall/commUtils.ts index 426841a..57bfde7 100644 --- a/src/childProcessCall/commUtils.ts +++ b/src/childProcessCall/commUtils.ts @@ -120,81 +120,6 @@ class CommUtils { .replace(/('X-CSRFToken'\s*:\s*)'.*?'/, "$1") .replace(/('set-cookie'\s*:\s*)\[.*?\]/, "$1"); } - - 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 commUtils: CommUtils = new CommUtils(); diff --git a/src/childProcessCall/commands/cache.ts b/src/childProcessCall/commands/cache.ts deleted file mode 100644 index 4af66a5..0000000 --- a/src/childProcessCall/commands/cache.ts +++ /dev/null @@ -1,52 +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 { commUtils } from "../commUtils"; -import { storageUtils } from "../storageUtils"; -import { session } from "../session"; - -class CacheCommand { - constructor() {} - - process_argv = function (argv) { - let argv_config = commUtils.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/list.ts b/src/childProcessCall/commands/list.ts deleted file mode 100644 index 4dcd2e3..0000000 --- a/src/childProcessCall/commands/list.ts +++ /dev/null @@ -1,71 +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 { commUtils } from "../commUtils"; -import { reply } from "../Reply"; -import { corePlugin } from "../core"; -import { session } from "../session"; - -class ListCommand { - constructor() {} - - process_argv(argv) { - let argv_config = commUtils - .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 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 listCommand: ListCommand = new ListCommand(); diff --git a/src/childProcessCall/commands/star.ts b/src/childProcessCall/commands/star.ts deleted file mode 100644 index fec2272..0000000 --- a/src/childProcessCall/commands/star.ts +++ /dev/null @@ -1,57 +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 { commUtils } from "../commUtils"; -import { reply } from "../Reply"; -import { corePlugin } from "../core"; -import { session } from "../session"; - -class StarCommand { - constructor() {} - - process_argv(argv) { - let argv_config = commUtils - .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 reply.info(e); - - corePlugin.starProblem(problem, !argv.delete, function (e, starred) { - if (e) return reply.info(e); - reply.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/factory/api/cache.ts b/src/childProcessCall/factory/api/cache.ts new file mode 100644 index 0000000..a9711d7 --- /dev/null +++ b/src/childProcessCall/factory/api/cache.ts @@ -0,0 +1,52 @@ +/* + * Filename: /home/cc/vscode-leetcode-problem-rating/src/childProcessCall/factory/api/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 { storageUtils } from "../../storageUtils"; +import { session } from "../../session"; +import { ApiBase } from "../apiFactory"; + +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) { + 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 cacheApi: CacheApi = new CacheApi(); diff --git a/src/childProcessCall/factory/api/list.ts b/src/childProcessCall/factory/api/list.ts new file mode 100644 index 0000000..1580aa6 --- /dev/null +++ b/src/childProcessCall/factory/api/list.ts @@ -0,0 +1,91 @@ +/* + * Filename: /home/cc/vscode-leetcode-problem-rating/src/childProcessCall/factory/api/list.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 { reply } from "../../Reply"; +import { session } from "../../session"; +import { ApiBase } from "../apiFactory"; +import { chain } from "../../actionChain/chain"; + +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) { + session.argv = argv; + chain.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/childProcessCall/commands/plugin.ts b/src/childProcessCall/factory/api/plugin.ts similarity index 63% rename from src/childProcessCall/commands/plugin.ts rename to src/childProcessCall/factory/api/plugin.ts index 75945a1..47cedf2 100644 --- a/src/childProcessCall/commands/plugin.ts +++ b/src/childProcessCall/factory/api/plugin.ts @@ -1,24 +1,25 @@ /* - * 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 + * Filename: /home/cc/vscode-leetcode-problem-rating/src/childProcessCall/factory/api/plugin.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 { commUtils } from "../commUtils"; -import { config } from "../config"; -import { reply } from "../Reply"; -import { myPluginBase } from "../my_plugin_base"; -import { session } from "../session"; +import { config } from "../../config"; +import { reply } from "../../Reply"; +import { chain } from "../../actionChain/chain"; +import { session } from "../../session"; +import { ApiBase } from "../apiFactory"; -class PluginCommand { - constructor() {} +class PluginApi extends ApiBase { + constructor() { + super(); + } - process_argv = function (argv) { - let argv_config = commUtils - .base_argv() + callArg(argv) { + let argv_config = this.api_argv() .option("d", { alias: "disable", type: "boolean", @@ -43,15 +44,15 @@ class PluginCommand { default: "", }); - argv_config.process_argv(argv); + argv_config.parseArgFromCmd(argv); return argv_config.get_result(); - }; + } - handler = function (argv) { + call(argv) { session.argv = argv; - let all_plugin = myPluginBase.installed; + let all_plugin = chain.installed; const name = argv.name; // if (argv.install) { @@ -59,7 +60,7 @@ class PluginCommand { // if (e) return log.fatal(e); // p.help(); // p.save(); - // myPluginBase.init(); + // chain.init(); // }; // return; @@ -82,11 +83,11 @@ class PluginCommand { } else if (argv.delete) { // p.delete(); p.save(); - myPluginBase.init(); + chain.init(); } else if (argv.config) { reply.info(JSON.stringify(config.plugins[name] || {}, null, 2)); } - }; + } } -export const pluginCommand: PluginCommand = new PluginCommand(); +export const pluginApi: PluginApi = new PluginApi(); diff --git a/src/childProcessCall/commands/query.ts b/src/childProcessCall/factory/api/query.ts similarity index 63% rename from src/childProcessCall/commands/query.ts rename to src/childProcessCall/factory/api/query.ts index 3996cdd..a559fb7 100644 --- a/src/childProcessCall/commands/query.ts +++ b/src/childProcessCall/factory/api/query.ts @@ -1,22 +1,24 @@ /* - * 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 + * Filename: /home/cc/vscode-leetcode-problem-rating/src/childProcessCall/factory/api/query.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 { commUtils } from "../commUtils"; -import { reply } from "../Reply"; -import { corePlugin } from "../core"; -import { session } from "../session"; +import { reply } from "../../Reply"; +import { session } from "../../session"; +import { ApiBase } from "../apiFactory"; -class QueryCommand { - constructor() {} - process_argv = function (argv) { - let argv_config = commUtils - .base_argv() +import { chain } from "../../actionChain/chain"; + +class QueryApi extends ApiBase { + constructor() { + super(); + } + callArg(argv) { + let argv_config = this.api_argv() .option("T", { alias: "dontTranslate", type: "boolean", @@ -47,24 +49,24 @@ class QueryCommand { default: "", describe: "test", }); - argv_config.process_argv(argv); + argv_config.parseArgFromCmd(argv); return argv_config.get_result(); - }; + } - handler = function (argv) { + call(argv) { session.argv = argv; if (argv.a) { - corePlugin.getTodayQuestion(function (e, result) { + chain.getChainHead().getTodayQuestion(function (e, result) { if (e) return; reply.info(JSON.stringify(result)); }); } else if (argv.b) { - corePlugin.getUserContest(argv.b, function (e, result) { + chain.getChainHead().getUserContest(argv.b, function (e, result) { if (e) return; reply.info(JSON.stringify(result)); }); } else if (argv.c) { - corePlugin.getRating(function (e, result) { + chain.getChainHead().getRating(function (e, result) { if (e) { let log_data = { code: 101, @@ -80,12 +82,12 @@ class QueryCommand { reply.info(JSON.stringify(log_data)); }); } else if (argv.z) { - corePlugin.getQueryZ(argv.z, function (e, result) { + chain.getChainHead().getQueryZ(argv.z, function (e, result) { if (e) return; reply.info(JSON.stringify(result)); }); } - }; + } } -export const queryCommand: QueryCommand = new QueryCommand(); +export const queryApi: QueryApi = new QueryApi(); diff --git a/src/childProcessCall/commands/show.ts b/src/childProcessCall/factory/api/show.ts similarity index 74% rename from src/childProcessCall/commands/show.ts rename to src/childProcessCall/factory/api/show.ts index baefa95..253773d 100644 --- a/src/childProcessCall/commands/show.ts +++ b/src/childProcessCall/factory/api/show.ts @@ -1,7 +1,7 @@ /* - * 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 + * Filename: /home/cc/vscode-leetcode-problem-rating/src/childProcessCall/factory/api/show.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. @@ -10,20 +10,23 @@ let util = require("util"); let childProcess = require("child_process"); -import { commUtils } from "../commUtils"; -import { storageUtils } from "../storageUtils"; +import { storageUtils } from "../../storageUtils"; -import { reply } from "../Reply"; -import { config } from "../config"; -import { corePlugin } from "../core"; -import { session } from "../session"; +import { reply } from "../../Reply"; +import { config } from "../../config"; -class ShowCommand { - constructor() {} +import { session } from "../../session"; +import { ApiBase } from "../apiFactory"; +import { commUtils } from "../../commUtils"; +import { chain } from "../../actionChain/chain"; - process_argv = function (argv) { - let argv_config = commUtils - .base_argv() +class ShowApi extends ApiBase { + constructor() { + super(); + } + + callArg(argv) { + let argv_config = this.api_argv() .option("c", { alias: "codeonly", type: "boolean", @@ -54,8 +57,27 @@ class ShowCommand { describe: "Where to save source code", default: ".", }) - .option("q", corePlugin.filters.query) - .option("t", corePlugin.filters.tag) + .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", @@ -73,9 +95,9 @@ class ShowCommand { default: "", describe: "Show question by name or id", }); - argv_config.process_argv(argv); + argv_config.parseArgFromCmd(argv); return argv_config.get_result(); - }; + } genFileName(problem, opts) { const path = require("path"); const params = [ @@ -121,7 +143,7 @@ class ShowCommand { code: template.defaultCode, tpl: argv.extra ? "detailed" : "codeonly", }; - code = corePlugin.exportProblem(problem, opts); + code = chain.getChainHead().exportProblem(problem, opts); } let filename; @@ -177,23 +199,21 @@ class ShowCommand { reply.info(problem.desc); } - handler(argv) { + call(argv) { let that = this; session.argv = argv; if (argv.keyword.length > 0) { // show specific one - corePlugin.getProblem( - argv.keyword, - !argv.dontTranslate, - function (e, problem) { + chain + .getChainHead() + .getProblem(argv.keyword, !argv.dontTranslate, function (e, problem) { if (e) return reply.info(e); that.showProblem(problem, argv); - } - ); + }); } else { // } } } -export const showCommand: ShowCommand = new ShowCommand(); +export const showApi: ShowApi = new ShowApi(); diff --git a/src/childProcessCall/factory/api/star.ts b/src/childProcessCall/factory/api/star.ts new file mode 100644 index 0000000..c558d62 --- /dev/null +++ b/src/childProcessCall/factory/api/star.ts @@ -0,0 +1,61 @@ +/* + * Filename: /home/cc/vscode-leetcode-problem-rating/src/childProcessCall/factory/api/star.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 { reply } from "../../Reply"; + +import { session } from "../../session"; +import { ApiBase } from "../apiFactory"; +import { chain } from "../../actionChain/chain"; + +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) { + session.argv = argv; + // translation doesn't affect question lookup + chain.getChainHead().getProblem(argv.keyword, true, function (e, problem) { + if (e) return reply.info(e); + + chain + .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" + }` + ); + chain.getChainHead().updateProblem(problem, { starred: starred }); + }); + }); + } +} + +export const starApi: StarApi = new StarApi(); diff --git a/src/childProcessCall/commands/submission.ts b/src/childProcessCall/factory/api/submission.ts similarity index 92% rename from src/childProcessCall/commands/submission.ts rename to src/childProcessCall/factory/api/submission.ts index b4f0e79..d8b7dfa 100644 --- a/src/childProcessCall/commands/submission.ts +++ b/src/childProcessCall/factory/api/submission.ts @@ -1,7 +1,7 @@ /* - * 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/childProcessCall/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. @@ -22,8 +22,8 @@ class SubMission { constructor() {} - // process_argv = function (argv) { - // let argv_config = commUtils.base_argv().option('a', { + // callArg = function (argv) { + // let argv_config = this.api_argv().option('a', { // alias: 'all', // type: 'boolean', // default: false, @@ -58,7 +58,7 @@ class SubMission { // default: '', // describe: 'Download specific question by id' // }); - // argv_config.process_argv(argv); + // argv_config.parseArgFromCmd(argv); // return argv_config.get_result(); // }; diff --git a/src/childProcessCall/commands/submit.ts b/src/childProcessCall/factory/api/submit.ts similarity index 79% rename from src/childProcessCall/commands/submit.ts rename to src/childProcessCall/factory/api/submit.ts index b8d2eda..ed7db2a 100644 --- a/src/childProcessCall/commands/submit.ts +++ b/src/childProcessCall/factory/api/submit.ts @@ -1,7 +1,7 @@ /* - * 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 + * Filename: /home/cc/vscode-leetcode-problem-rating/src/childProcessCall/factory/api/submit.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. @@ -10,22 +10,25 @@ let util = require("util"); let lodash = require("lodash"); -import { commUtils } from "../commUtils"; -import { storageUtils } from "../storageUtils"; -import { reply } from "../Reply"; -import { corePlugin } from "../core"; -import { session } from "../session"; +import { storageUtils } from "../../storageUtils"; +import { reply } from "../../Reply"; -class SubmitCommand { - constructor() {} +import { session } from "../../session"; +import { ApiBase } from "../apiFactory"; +import { chain } from "../../actionChain/chain"; - process_argv(argv) { - let argv_config = commUtils.base_argv().positional("filename", { +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.process_argv(argv); + argv_config.parseArgFromCmd(argv); return argv_config.get_result(); } @@ -54,7 +57,7 @@ class SubmitCommand { log_obj.messages.push(line); } - handler(argv) { + call(argv) { session.argv = argv; if (!storageUtils.exist(argv.filename)) return reply.fatal("File " + argv.filename + " not exist!"); @@ -62,13 +65,13 @@ class SubmitCommand { const meta = storageUtils.meta(argv.filename); let that = this; // translation doesn't affect problem lookup - corePlugin.getProblem(meta, true, function (e, problem) { + chain.getChainHead().getProblem(meta, true, function (e, problem) { if (e) return reply.info(e); problem.file = argv.filename; problem.lang = meta.lang; - corePlugin.submitProblem(problem, function (e, results) { + chain.getChainHead().submitProblem(problem, function (e, results) { if (e) return reply.info(e); const result = results[0]; @@ -127,7 +130,7 @@ class SubmitCommand { that.printResult(result, "stdout", log_obj); } reply.info(JSON.stringify(log_obj)); - corePlugin.updateProblem(problem, { + chain.getChainHead().updateProblem(problem, { state: result.ok ? "ac" : "notac", }); }); @@ -135,4 +138,4 @@ class SubmitCommand { } } -export const submitCommand: SubmitCommand = new SubmitCommand(); +export const submitApi: SubmitApi = new SubmitApi(); diff --git a/src/childProcessCall/commands/test.ts b/src/childProcessCall/factory/api/test.ts similarity index 88% rename from src/childProcessCall/commands/test.ts rename to src/childProcessCall/factory/api/test.ts index 0d97195..b342739 100644 --- a/src/childProcessCall/commands/test.ts +++ b/src/childProcessCall/factory/api/test.ts @@ -1,7 +1,7 @@ /* - * 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 + * Filename: /home/cc/vscode-leetcode-problem-rating/src/childProcessCall/factory/api/test.ts + * Path: /home/cc/vscode-leetcode-problem-rating + * Created Date: Wednesday, November 16th 2022, 3:13:59 pm * Author: ccagml * * Copyright (c) 2022 ccagml . All rights reserved. @@ -10,18 +10,21 @@ let _ = require("underscore"); let lodash = require("lodash"); -import { commUtils } from "../commUtils"; -import { storageUtils } from "../storageUtils"; -import { reply } from "../Reply"; -import { corePlugin } from "../core"; -import { session } from "../session"; +import { storageUtils } from "../../storageUtils"; +import { reply } from "../../Reply"; -class TestCommand { - constructor() {} +import { session } from "../../session"; +import { ApiBase } from "../apiFactory"; +import { commUtils } from "../../commUtils"; +import { chain } from "../../actionChain/chain"; - process_argv(argv) { - let argv_config = commUtils - .base_argv() +class TestApi extends ApiBase { + constructor() { + super(); + } + + callArg(argv) { + let argv_config = this.api_argv() .option("i", { alias: "interactive", type: "boolean", @@ -46,7 +49,7 @@ class TestCommand { describe: "Code file to test", }); - argv_config.process_argv(argv); + argv_config.parseArgFromCmd(argv); return argv_config.get_result(); } @@ -85,7 +88,7 @@ class TestCommand { // [key: string]: string[]; // messages: string[]; - corePlugin.getProblem(meta, true, function (e, problem) { + chain.getChainHead().getProblem(meta, true, function (e, problem) { if (e) return reply.info( JSON.stringify({ @@ -190,7 +193,7 @@ class TestCommand { problem.file = argv.filename; problem.lang = meta.lang; - corePlugin.testProblem(problem, function (e, results) { + chain.getChainHead().testProblem(problem, function (e, results) { if (e) return reply.info(JSON.stringify(e)); results = _.sortBy(results, (x) => x.type); @@ -229,7 +232,7 @@ class TestCommand { }); } - handler(argv) { + call(argv) { let that = this; session.argv = argv; if (!argv.i) return that.runTest(argv); @@ -243,4 +246,4 @@ class TestCommand { } } -export const testCommand: TestCommand = new TestCommand(); +export const testApi: TestApi = new TestApi(); diff --git a/src/childProcessCall/commands/user.ts b/src/childProcessCall/factory/api/user.ts similarity index 78% rename from src/childProcessCall/commands/user.ts rename to src/childProcessCall/factory/api/user.ts index 8f114e2..1e9a5ec 100644 --- a/src/childProcessCall/commands/user.ts +++ b/src/childProcessCall/factory/api/user.ts @@ -1,24 +1,28 @@ /* - * 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 + * Filename: /home/cc/vscode-leetcode-problem-rating/src/childProcessCall/factory/api/user.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 prompt_out = require("prompt"); -import { commUtils } from "../commUtils"; -import { reply } from "../Reply"; -import { corePlugin } from "../core"; -import { session } from "../session"; -class UserCommand { - constructor() {} +import { reply } from "../../Reply"; - process_argv(argv) { - let argv_config = commUtils - .base_argv() +import { session } from "../../session"; +import { ApiBase } from "../apiFactory"; + +import { chain } from "../../actionChain/chain"; + +class UserApi extends ApiBase { + constructor() { + super(); + } + + callArg(argv) { + let argv_config = this.api_argv() .option("l", { alias: "login", type: "boolean", @@ -50,12 +54,12 @@ class UserCommand { describe: "Logout", }); - argv_config.process_argv(argv); + argv_config.parseArgFromCmd(argv); return argv_config.get_result(); } - handler(argv) { + call(argv) { session.argv = argv; let user: any = null; if (argv.login) { @@ -73,7 +77,7 @@ class UserCommand { return reply.info(JSON.stringify({ code: -1, msg: e.msg || e })); } - corePlugin.login(user, function (e, user) { + chain.getChainHead().login(user, function (e, user) { if (e) { return reply.info(JSON.stringify({ code: -2, msg: e.msg || e })); } @@ -83,7 +87,7 @@ class UserCommand { ); } else if (argv.logout) { // logout - user = corePlugin.logout(user, true); + user = chain.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?" })); @@ -91,10 +95,10 @@ class UserCommand { } 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], + ["g", chain.getChainHead().githubLogin], + ["github", chain.getChainHead().githubLogin], + ["i", chain.getChainHead().linkedinLogin], + ["linkedin", chain.getChainHead().linkedinLogin], ]); const keyword = Object.entries(argv).filter((i) => i[1] === true)[0][0]; const coreFunction = functionMap.get(keyword); @@ -132,7 +136,7 @@ class UserCommand { ], function (e, user) { if (e) return reply.info(e); - corePlugin.cookieLogin(user, function (e, user) { + chain.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 })); @@ -152,4 +156,4 @@ class UserCommand { } } -export const userCommand: UserCommand = new UserCommand(); +export const userApi: UserApi = new UserApi(); diff --git a/src/childProcessCall/factory/apiFactory.ts b/src/childProcessCall/factory/apiFactory.ts new file mode 100644 index 0000000..77896e7 --- /dev/null +++ b/src/childProcessCall/factory/apiFactory.ts @@ -0,0 +1,124 @@ +import { cacheApi } from "./api/cache"; +import { listApi } from "./api/list"; +import { pluginApi } from "./api/plugin"; +import { queryApi } from "./api/query"; +import { showApi } from "./api/show"; +import { starApi } from "./api/star"; +import { submitApi } from "./api/submit"; +import { testApi } from "./api/test"; +import { userApi } from "./api/user"; + +export interface IApi { + callArg(arg); + call(arg): void; +} + +export class ApiBase implements IApi { + 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; + } +} + +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(); From a06b8f6b7e98cf243e1fd5d7511f907219849ccc Mon Sep 17 00:00:00 2001 From: ccagml Date: Thu, 17 Nov 2022 11:15:48 +0800 Subject: [PATCH 05/26] update --- src/childProcessCall/actionChain/chain.ts | 4 +- .../actionChain/chainNode/core.ts | 2 +- src/childProcessCall/cli.ts | 3 +- src/childProcessCall/factory/api/cache.ts | 4 +- src/childProcessCall/factory/api/list.ts | 2 +- src/childProcessCall/factory/api/plugin.ts | 2 +- src/childProcessCall/factory/api/query.ts | 2 +- src/childProcessCall/factory/api/show.ts | 2 +- src/childProcessCall/factory/api/star.ts | 2 +- src/childProcessCall/factory/api/submit.ts | 2 +- src/childProcessCall/factory/api/test.ts | 2 +- src/childProcessCall/factory/api/user.ts | 2 +- src/childProcessCall/factory/apiFactory.ts | 89 +------------------ src/childProcessCall/factory/baseApi.ts | 88 ++++++++++++++++++ src/controller/LoginController.ts | 2 +- 15 files changed, 106 insertions(+), 102 deletions(-) create mode 100644 src/childProcessCall/factory/baseApi.ts diff --git a/src/childProcessCall/actionChain/chain.ts b/src/childProcessCall/actionChain/chain.ts index 6cfca26..ea04f0a 100644 --- a/src/childProcessCall/actionChain/chain.ts +++ b/src/childProcessCall/actionChain/chain.ts @@ -50,7 +50,9 @@ export class Chain { public base_init(head): Object { this.head = head; const stats = storageUtils.getCache(commUtils.KEYS.plugins) || {}; - let file_plugin: Array = storageUtils.listCodeDir("plugins"); + let file_plugin: Array = storageUtils.listCodeDir( + "actionChain/chainNode" + ); this.installed = []; for (let f of file_plugin) { const p = f.data; diff --git a/src/childProcessCall/actionChain/chainNode/core.ts b/src/childProcessCall/actionChain/chainNode/core.ts index 48dbbb9..49a5bde 100644 --- a/src/childProcessCall/actionChain/chainNode/core.ts +++ b/src/childProcessCall/actionChain/chainNode/core.ts @@ -89,7 +89,7 @@ class CorePlugin extends Chain { // unify format before rendering - data.app = require("./config").app || "leetcode"; + data.app = require("./../../config").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"); diff --git a/src/childProcessCall/cli.ts b/src/childProcessCall/cli.ts index 08bc167..f23677d 100644 --- a/src/childProcessCall/cli.ts +++ b/src/childProcessCall/cli.ts @@ -12,7 +12,8 @@ import { corePlugin } from "./actionChain/chainNode/core"; import { config } from "./config"; import { reply } from "./Reply"; import { storageUtils } from "./storageUtils"; -import { IApi, apiFactory } from "./factory/apiFactory"; +import { apiFactory } from "./factory/apiFactory"; +import { IApi } from "./factory/baseApi"; class NewCli { constructor() { diff --git a/src/childProcessCall/factory/api/cache.ts b/src/childProcessCall/factory/api/cache.ts index a9711d7..03c9dca 100644 --- a/src/childProcessCall/factory/api/cache.ts +++ b/src/childProcessCall/factory/api/cache.ts @@ -9,7 +9,7 @@ import { storageUtils } from "../../storageUtils"; import { session } from "../../session"; -import { ApiBase } from "../apiFactory"; +import { ApiBase } from "../baseApi"; class CacheApi extends ApiBase { constructor() { @@ -31,7 +31,7 @@ class CacheApi extends ApiBase { call(argv) { session.argv = argv; - const name = argv.keyword; + const name = argv.keyword || ""; const isInteger = Number.isInteger(Number(name)); const all_data_file = storageUtils.listCache().filter(function (f) { diff --git a/src/childProcessCall/factory/api/list.ts b/src/childProcessCall/factory/api/list.ts index 1580aa6..0e8997a 100644 --- a/src/childProcessCall/factory/api/list.ts +++ b/src/childProcessCall/factory/api/list.ts @@ -9,7 +9,7 @@ import { reply } from "../../Reply"; import { session } from "../../session"; -import { ApiBase } from "../apiFactory"; +import { ApiBase } from "../baseApi"; import { chain } from "../../actionChain/chain"; class ListApi extends ApiBase { diff --git a/src/childProcessCall/factory/api/plugin.ts b/src/childProcessCall/factory/api/plugin.ts index 47cedf2..5e967bc 100644 --- a/src/childProcessCall/factory/api/plugin.ts +++ b/src/childProcessCall/factory/api/plugin.ts @@ -11,7 +11,7 @@ import { config } from "../../config"; import { reply } from "../../Reply"; import { chain } from "../../actionChain/chain"; import { session } from "../../session"; -import { ApiBase } from "../apiFactory"; +import { ApiBase } from "../baseApi"; class PluginApi extends ApiBase { constructor() { diff --git a/src/childProcessCall/factory/api/query.ts b/src/childProcessCall/factory/api/query.ts index a559fb7..67a9cf7 100644 --- a/src/childProcessCall/factory/api/query.ts +++ b/src/childProcessCall/factory/api/query.ts @@ -9,7 +9,7 @@ import { reply } from "../../Reply"; import { session } from "../../session"; -import { ApiBase } from "../apiFactory"; +import { ApiBase } from "../baseApi"; import { chain } from "../../actionChain/chain"; diff --git a/src/childProcessCall/factory/api/show.ts b/src/childProcessCall/factory/api/show.ts index 253773d..eae929b 100644 --- a/src/childProcessCall/factory/api/show.ts +++ b/src/childProcessCall/factory/api/show.ts @@ -16,7 +16,7 @@ import { reply } from "../../Reply"; import { config } from "../../config"; import { session } from "../../session"; -import { ApiBase } from "../apiFactory"; +import { ApiBase } from "../baseApi"; import { commUtils } from "../../commUtils"; import { chain } from "../../actionChain/chain"; diff --git a/src/childProcessCall/factory/api/star.ts b/src/childProcessCall/factory/api/star.ts index c558d62..18c6748 100644 --- a/src/childProcessCall/factory/api/star.ts +++ b/src/childProcessCall/factory/api/star.ts @@ -10,7 +10,7 @@ import { reply } from "../../Reply"; import { session } from "../../session"; -import { ApiBase } from "../apiFactory"; +import { ApiBase } from "../baseApi"; import { chain } from "../../actionChain/chain"; class StarApi extends ApiBase { diff --git a/src/childProcessCall/factory/api/submit.ts b/src/childProcessCall/factory/api/submit.ts index ed7db2a..0dbdd32 100644 --- a/src/childProcessCall/factory/api/submit.ts +++ b/src/childProcessCall/factory/api/submit.ts @@ -14,7 +14,7 @@ import { storageUtils } from "../../storageUtils"; import { reply } from "../../Reply"; import { session } from "../../session"; -import { ApiBase } from "../apiFactory"; +import { ApiBase } from "../baseApi"; import { chain } from "../../actionChain/chain"; class SubmitApi extends ApiBase { diff --git a/src/childProcessCall/factory/api/test.ts b/src/childProcessCall/factory/api/test.ts index b342739..d702449 100644 --- a/src/childProcessCall/factory/api/test.ts +++ b/src/childProcessCall/factory/api/test.ts @@ -14,7 +14,7 @@ import { storageUtils } from "../../storageUtils"; import { reply } from "../../Reply"; import { session } from "../../session"; -import { ApiBase } from "../apiFactory"; +import { ApiBase } from "../baseApi"; import { commUtils } from "../../commUtils"; import { chain } from "../../actionChain/chain"; diff --git a/src/childProcessCall/factory/api/user.ts b/src/childProcessCall/factory/api/user.ts index 1e9a5ec..51df7d1 100644 --- a/src/childProcessCall/factory/api/user.ts +++ b/src/childProcessCall/factory/api/user.ts @@ -12,7 +12,7 @@ let prompt_out = require("prompt"); import { reply } from "../../Reply"; import { session } from "../../session"; -import { ApiBase } from "../apiFactory"; +import { ApiBase } from "../baseApi"; import { chain } from "../../actionChain/chain"; diff --git a/src/childProcessCall/factory/apiFactory.ts b/src/childProcessCall/factory/apiFactory.ts index 77896e7..b6bdaef 100644 --- a/src/childProcessCall/factory/apiFactory.ts +++ b/src/childProcessCall/factory/apiFactory.ts @@ -7,94 +7,7 @@ import { starApi } from "./api/star"; import { submitApi } from "./api/submit"; import { testApi } from "./api/test"; import { userApi } from "./api/user"; - -export interface IApi { - callArg(arg); - call(arg): void; -} - -export class ApiBase implements IApi { - 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; - } -} +import { IApi } from "./baseApi"; class ApiFactory { constructor() {} diff --git a/src/childProcessCall/factory/baseApi.ts b/src/childProcessCall/factory/baseApi.ts new file mode 100644 index 0000000..4030df7 --- /dev/null +++ b/src/childProcessCall/factory/baseApi.ts @@ -0,0 +1,88 @@ +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/controller/LoginController.ts b/src/controller/LoginController.ts index 944d1bc..bf8d90d 100644 --- a/src/controller/LoginController.ts +++ b/src/controller/LoginController.ts @@ -185,8 +185,8 @@ class LoginContorller { } ); if (userName) { - window.showInformationMessage(`${inMessage} 成功`); eventService.emit("statusChanged", UserStatus.SignedIn, userName); + window.showInformationMessage(`${inMessage} 成功`); } } catch (error) { promptForOpenOutputChannel( From 90ec983beae45d73c0a26bbe7fe9ea8c1120fdec Mon Sep 17 00:00:00 2001 From: ccagml Date: Thu, 17 Nov 2022 11:32:03 +0800 Subject: [PATCH 06/26] update --- .../actionChain/chainNode/leetcode.ts | 2 +- src/childProcessCall/commUtils.ts | 40 +------------------ src/childProcessCall/factory/api/show.ts | 6 +-- 3 files changed, 3 insertions(+), 45 deletions(-) diff --git a/src/childProcessCall/actionChain/chainNode/leetcode.ts b/src/childProcessCall/actionChain/chainNode/leetcode.ts index 0c804e8..8b63ffc 100644 --- a/src/childProcessCall/actionChain/chainNode/leetcode.ts +++ b/src/childProcessCall/actionChain/chainNode/leetcode.ts @@ -117,7 +117,7 @@ class LeetCode extends Chain { ), locked: p.paid_only, percent: (p.stat.total_acs * 100) / p.stat.total_submitted, - level: commUtils.levelToName(p.difficulty.level), + level: commUtils.getNameByLevel(p.difficulty.level), starred: p.is_favor, category: json.category_slug, }; diff --git a/src/childProcessCall/commUtils.ts b/src/childProcessCall/commUtils.ts index 57bfde7..96e9a61 100644 --- a/src/childProcessCall/commUtils.ts +++ b/src/childProcessCall/commUtils.ts @@ -23,20 +23,7 @@ class CommUtils { }; } - prettyLevel(level) { - switch (level.toLowerCase().trim()) { - case "easy": - return level; - case "medium": - return level; - case "hard": - return level; - default: - return level; - } - } - - levelToName(level) { + getNameByLevel(level) { switch (level) { case 1: return "Easy"; @@ -49,31 +36,6 @@ class CommUtils { } } - 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"; - } - } - readStdin(cb) { const stdin = process.stdin; let bufs: Array = []; diff --git a/src/childProcessCall/factory/api/show.ts b/src/childProcessCall/factory/api/show.ts index eae929b..e6f02e8 100644 --- a/src/childProcessCall/factory/api/show.ts +++ b/src/childProcessCall/factory/api/show.ts @@ -177,11 +177,7 @@ class ShowApi extends ApiBase { reply.info(); reply.info(`* ${problem.category}`); - reply.info( - `* ${commUtils.prettyLevel(problem.level)} (${problem.percent.toFixed( - 2 - )}%)` - ); + reply.info(`* ${problem.level} (${problem.percent.toFixed(2)}%)`); if (problem.likes) reply.info(`* Likes: ${problem.likes}`); if (problem.dislikes) reply.info(`* Dislikes: ${problem.dislikes}`); From e9f4b42197ca88ad93158daa0819a3a733557f52 Mon Sep 17 00:00:00 2001 From: ccagml Date: Thu, 17 Nov 2022 11:34:34 +0800 Subject: [PATCH 07/26] update --- .github/workflows/codeql-analysis.yml | 61 +++++++++++++-------------- 1 file changed, 29 insertions(+), 32 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 61ed33f..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. + # 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 + # 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 + # 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 - # 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 + # ℹ️ 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 - # ℹ️ 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 + # 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. - # 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. + # - run: | + # echo "Run, Build Application using script" + # ./location_of_script_within_repo/buildscript.sh - # - 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}}" + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v2 + with: + category: "/language:${{matrix.language}}" From 30b3688bb9fa936d73a51cbcb571400e38592ca5 Mon Sep 17 00:00:00 2001 From: ccagml Date: Thu, 17 Nov 2022 11:35:47 +0800 Subject: [PATCH 08/26] update --- src/childProcessCall/factory/api/show.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/childProcessCall/factory/api/show.ts b/src/childProcessCall/factory/api/show.ts index e6f02e8..5d6e239 100644 --- a/src/childProcessCall/factory/api/show.ts +++ b/src/childProcessCall/factory/api/show.ts @@ -17,7 +17,6 @@ import { config } from "../../config"; import { session } from "../../session"; import { ApiBase } from "../baseApi"; -import { commUtils } from "../../commUtils"; import { chain } from "../../actionChain/chain"; class ShowApi extends ApiBase { From 0dff03e71b0516aa8a213824b73f7e7106fcd1f1 Mon Sep 17 00:00:00 2001 From: ccagml Date: Thu, 17 Nov 2022 11:41:21 +0800 Subject: [PATCH 09/26] update --- src/childProcessCall/actionChain/chain.ts | 4 ++-- .../actionChain/chainNode/leetcode.cn.ts | 1 + .../actionChain/chainNode/leetcode.ts | 20 ++++++++++++------- 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/childProcessCall/actionChain/chain.ts b/src/childProcessCall/actionChain/chain.ts index ea04f0a..54470da 100644 --- a/src/childProcessCall/actionChain/chain.ts +++ b/src/childProcessCall/actionChain/chain.ts @@ -47,7 +47,7 @@ export class Chain { return this.head; } - public base_init(head): Object { + public base_init(head: Chain): Object { this.head = head; const stats = storageUtils.getCache(commUtils.KEYS.plugins) || {}; let file_plugin: Array = storageUtils.listCodeDir( @@ -87,7 +87,7 @@ export class Chain { return true; } - public setNext(next): void { + public setNext(next: Chain): void { Object.setPrototypeOf(this, next); this.next = next; } diff --git a/src/childProcessCall/actionChain/chainNode/leetcode.cn.ts b/src/childProcessCall/actionChain/chainNode/leetcode.cn.ts index 7b52d79..727adca 100644 --- a/src/childProcessCall/actionChain/chainNode/leetcode.cn.ts +++ b/src/childProcessCall/actionChain/chainNode/leetcode.cn.ts @@ -188,6 +188,7 @@ class LeetCodeCn extends Chain { ); }; + // eslint-disable-next-line @typescript-eslint/no-unused-vars getTestApi = (value: any, _) => { const _request = request.defaults({ jar: true }); _request( diff --git a/src/childProcessCall/actionChain/chainNode/leetcode.ts b/src/childProcessCall/actionChain/chainNode/leetcode.ts index 8b63ffc..00e4d45 100644 --- a/src/childProcessCall/actionChain/chainNode/leetcode.ts +++ b/src/childProcessCall/actionChain/chainNode/leetcode.ts @@ -394,14 +394,15 @@ class LeetCode extends Chain { }; 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) => { + getFavorites = (cb: any) => { const opts = this.makeOpts(config.sys.urls.favorites); let that = this; @@ -414,7 +415,7 @@ class LeetCode extends Chain { }); }; - getUserInfo = (cb) => { + getUserInfo = (cb: any) => { let that = this; const opts = this.makeOpts(config.sys.urls.graphql); opts.headers.Origin = config.sys.urls.base; @@ -441,7 +442,7 @@ class LeetCode extends Chain { }); }; - runSession = (method, data, cb) => { + runSession = (method: any, data: any, cb: any) => { const opts = this.makeOpts(config.sys.urls.session); opts.json = true; opts.method = method; @@ -475,9 +476,10 @@ class LeetCode extends Chain { this.runSession("DELETE", data, cb); }; - signin = (user, cb) => { + signin = (user: any, cb: any) => { let that = this; - request(config.sys.urls.login, function (e, resp, _) { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + request(config.sys.urls.login, function (e: any, resp: any, _) { e = that.checkError(e, resp, 200); if (e) return cb(e); user.loginCSRF = commUtils.getSetCookieValue(resp, "csrftoken"); @@ -494,7 +496,8 @@ class LeetCode extends Chain { 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?"); @@ -558,6 +561,7 @@ class LeetCode extends Chain { 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) { @@ -663,6 +667,7 @@ class LeetCode extends Chain { 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"); @@ -731,6 +736,7 @@ class LeetCode extends Chain { 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"); From 622c0b093f2831ea9eaf435fa5b6a8d3cfe18dd5 Mon Sep 17 00:00:00 2001 From: ccagml Date: Thu, 17 Nov 2022 11:47:29 +0800 Subject: [PATCH 10/26] update --- src/{childProcessCall => RemoteCall}/Reply.ts | 2 +- src/{childProcessCall => RemoteCall}/actionChain/chain.ts | 2 +- .../actionChain/chainNode/cache.ts | 2 +- .../actionChain/chainNode/core.ts | 2 +- .../actionChain/chainNode/leetcode.cn.ts | 2 +- .../actionChain/chainNode/leetcode.ts | 2 +- .../actionChain/chainNode/retry.ts | 2 +- .../actionChain/chainNode/solution.discuss.ts | 2 +- src/{childProcessCall => RemoteCall}/cli.ts | 2 +- src/{childProcessCall => RemoteCall}/commUtils.ts | 2 +- src/{childProcessCall => RemoteCall}/config.ts | 2 +- src/{childProcessCall => RemoteCall}/factory/api/cache.ts | 2 +- src/{childProcessCall => RemoteCall}/factory/api/list.ts | 2 +- src/{childProcessCall => RemoteCall}/factory/api/plugin.ts | 2 +- src/{childProcessCall => RemoteCall}/factory/api/query.ts | 2 +- src/{childProcessCall => RemoteCall}/factory/api/show.ts | 2 +- src/{childProcessCall => RemoteCall}/factory/api/star.ts | 2 +- .../factory/api/submission.ts | 2 +- src/{childProcessCall => RemoteCall}/factory/api/submit.ts | 2 +- src/{childProcessCall => RemoteCall}/factory/api/test.ts | 2 +- src/{childProcessCall => RemoteCall}/factory/api/user.ts | 2 +- src/{childProcessCall => RemoteCall}/factory/apiFactory.ts | 0 src/{childProcessCall => RemoteCall}/factory/baseApi.ts | 0 src/{childProcessCall => RemoteCall}/queue.ts | 2 +- src/{childProcessCall => RemoteCall}/session.ts | 2 +- src/{childProcessCall => RemoteCall}/storageUtils.ts | 2 +- src/service/ExecuteService.ts | 4 ++-- 27 files changed, 26 insertions(+), 26 deletions(-) rename src/{childProcessCall => RemoteCall}/Reply.ts (93%) rename src/{childProcessCall => RemoteCall}/actionChain/chain.ts (98%) rename src/{childProcessCall => RemoteCall}/actionChain/chainNode/cache.ts (97%) rename src/{childProcessCall => RemoteCall}/actionChain/chainNode/core.ts (97%) rename src/{childProcessCall => RemoteCall}/actionChain/chainNode/leetcode.cn.ts (98%) rename src/{childProcessCall => RemoteCall}/actionChain/chainNode/leetcode.ts (99%) rename src/{childProcessCall => RemoteCall}/actionChain/chainNode/retry.ts (95%) rename src/{childProcessCall => RemoteCall}/actionChain/chainNode/solution.discuss.ts (96%) rename src/{childProcessCall => RemoteCall}/cli.ts (97%) rename src/{childProcessCall => RemoteCall}/commUtils.ts (95%) rename src/{childProcessCall => RemoteCall}/config.ts (99%) rename src/{childProcessCall => RemoteCall}/factory/api/cache.ts (92%) rename src/{childProcessCall => RemoteCall}/factory/api/list.ts (96%) rename src/{childProcessCall => RemoteCall}/factory/api/plugin.ts (95%) rename src/{childProcessCall => RemoteCall}/factory/api/query.ts (96%) rename src/{childProcessCall => RemoteCall}/factory/api/show.ts (98%) rename src/{childProcessCall => RemoteCall}/factory/api/star.ts (94%) rename src/{childProcessCall => RemoteCall}/factory/api/submission.ts (98%) rename src/{childProcessCall => RemoteCall}/factory/api/submit.ts (97%) rename src/{childProcessCall => RemoteCall}/factory/api/test.ts (98%) rename src/{childProcessCall => RemoteCall}/factory/api/user.ts (97%) rename src/{childProcessCall => RemoteCall}/factory/apiFactory.ts (100%) rename src/{childProcessCall => RemoteCall}/factory/baseApi.ts (100%) rename src/{childProcessCall => RemoteCall}/queue.ts (97%) rename src/{childProcessCall => RemoteCall}/session.ts (98%) rename src/{childProcessCall => RemoteCall}/storageUtils.ts (99%) diff --git a/src/childProcessCall/Reply.ts b/src/RemoteCall/Reply.ts similarity index 93% rename from src/childProcessCall/Reply.ts rename to src/RemoteCall/Reply.ts index ffcbcc3..3dd7f3f 100644 --- a/src/childProcessCall/Reply.ts +++ b/src/RemoteCall/Reply.ts @@ -1,5 +1,5 @@ /* - * Filename: /home/cc/vscode-leetcode-problem-rating/src/childProcessCall/Response.ts + * Filename: /home/cc/vscode-leetcode-problem-rating/src/RemoteCall/Response.ts * Path: /home/cc/vscode-leetcode-problem-rating * Created Date: Monday, November 14th 2022, 4:04:31 pm * Author: ccagml diff --git a/src/childProcessCall/actionChain/chain.ts b/src/RemoteCall/actionChain/chain.ts similarity index 98% rename from src/childProcessCall/actionChain/chain.ts rename to src/RemoteCall/actionChain/chain.ts index 54470da..18f40ab 100644 --- a/src/childProcessCall/actionChain/chain.ts +++ b/src/RemoteCall/actionChain/chain.ts @@ -1,5 +1,5 @@ /* - * Filename: /home/cc/vscode-leetcode-problem-rating/src/childProcessCall/actionChain/chain.ts + * Filename: /home/cc/vscode-leetcode-problem-rating/src/RemoteCall/actionChain/chain.ts * Path: /home/cc/vscode-leetcode-problem-rating * Created Date: Monday, November 14th 2022, 4:04:31 pm * Author: ccagml diff --git a/src/childProcessCall/actionChain/chainNode/cache.ts b/src/RemoteCall/actionChain/chainNode/cache.ts similarity index 97% rename from src/childProcessCall/actionChain/chainNode/cache.ts rename to src/RemoteCall/actionChain/chainNode/cache.ts index 562f2a8..525b1fd 100644 --- a/src/childProcessCall/actionChain/chainNode/cache.ts +++ b/src/RemoteCall/actionChain/chainNode/cache.ts @@ -1,5 +1,5 @@ /* - * Filename: /home/cc/vscode-leetcode-problem-rating/src/childProcessCall/actionChain/cache.ts + * Filename: /home/cc/vscode-leetcode-problem-rating/src/RemoteCall/actionChain/cache.ts * Path: /home/cc/vscode-leetcode-problem-rating * Created Date: Monday, November 14th 2022, 4:04:31 pm * Author: ccagml diff --git a/src/childProcessCall/actionChain/chainNode/core.ts b/src/RemoteCall/actionChain/chainNode/core.ts similarity index 97% rename from src/childProcessCall/actionChain/chainNode/core.ts rename to src/RemoteCall/actionChain/chainNode/core.ts index 49a5bde..12c4c2d 100644 --- a/src/childProcessCall/actionChain/chainNode/core.ts +++ b/src/RemoteCall/actionChain/chainNode/core.ts @@ -1,5 +1,5 @@ /* - * Filename: /home/cc/vscode-leetcode-problem-rating/src/childProcessCall/actionChain/core.ts + * Filename: /home/cc/vscode-leetcode-problem-rating/src/RemoteCall/actionChain/core.ts * Path: /home/cc/vscode-leetcode-problem-rating * Created Date: Monday, November 14th 2022, 4:04:31 pm * Author: ccagml diff --git a/src/childProcessCall/actionChain/chainNode/leetcode.cn.ts b/src/RemoteCall/actionChain/chainNode/leetcode.cn.ts similarity index 98% rename from src/childProcessCall/actionChain/chainNode/leetcode.cn.ts rename to src/RemoteCall/actionChain/chainNode/leetcode.cn.ts index 727adca..ec3d494 100644 --- a/src/childProcessCall/actionChain/chainNode/leetcode.cn.ts +++ b/src/RemoteCall/actionChain/chainNode/leetcode.cn.ts @@ -1,5 +1,5 @@ /* - * Filename: /home/cc/vscode-leetcode-problem-rating/src/childProcessCall/actionChain/leetcode.cn.ts + * Filename: /home/cc/vscode-leetcode-problem-rating/src/RemoteCall/actionChain/leetcode.cn.ts * Path: /home/cc/vscode-leetcode-problem-rating * Created Date: Monday, November 14th 2022, 4:04:31 pm * Author: ccagml diff --git a/src/childProcessCall/actionChain/chainNode/leetcode.ts b/src/RemoteCall/actionChain/chainNode/leetcode.ts similarity index 99% rename from src/childProcessCall/actionChain/chainNode/leetcode.ts rename to src/RemoteCall/actionChain/chainNode/leetcode.ts index 00e4d45..7d6325c 100644 --- a/src/childProcessCall/actionChain/chainNode/leetcode.ts +++ b/src/RemoteCall/actionChain/chainNode/leetcode.ts @@ -1,5 +1,5 @@ /* - * Filename: /home/cc/vscode-leetcode-problem-rating/src/childProcessCall/actionChain/leetcode.ts + * Filename: /home/cc/vscode-leetcode-problem-rating/src/RemoteCall/actionChain/leetcode.ts * Path: /home/cc/vscode-leetcode-problem-rating * Created Date: Monday, November 14th 2022, 4:04:31 pm * Author: ccagml diff --git a/src/childProcessCall/actionChain/chainNode/retry.ts b/src/RemoteCall/actionChain/chainNode/retry.ts similarity index 95% rename from src/childProcessCall/actionChain/chainNode/retry.ts rename to src/RemoteCall/actionChain/chainNode/retry.ts index b201e49..56a384b 100644 --- a/src/childProcessCall/actionChain/chainNode/retry.ts +++ b/src/RemoteCall/actionChain/chainNode/retry.ts @@ -1,5 +1,5 @@ /* - * Filename: /home/cc/vscode-leetcode-problem-rating/src/childProcessCall/actionChain/retry.ts + * Filename: /home/cc/vscode-leetcode-problem-rating/src/RemoteCall/actionChain/retry.ts * Path: /home/cc/vscode-leetcode-problem-rating * Created Date: Monday, November 14th 2022, 4:04:31 pm * Author: ccagml diff --git a/src/childProcessCall/actionChain/chainNode/solution.discuss.ts b/src/RemoteCall/actionChain/chainNode/solution.discuss.ts similarity index 96% rename from src/childProcessCall/actionChain/chainNode/solution.discuss.ts rename to src/RemoteCall/actionChain/chainNode/solution.discuss.ts index db56367..9f599ea 100644 --- a/src/childProcessCall/actionChain/chainNode/solution.discuss.ts +++ b/src/RemoteCall/actionChain/chainNode/solution.discuss.ts @@ -1,5 +1,5 @@ /* - * Filename: /home/cc/vscode-leetcode-problem-rating/src/childProcessCall/actionChain/solution.discuss.ts + * Filename: /home/cc/vscode-leetcode-problem-rating/src/RemoteCall/actionChain/solution.discuss.ts * Path: /home/cc/vscode-leetcode-problem-rating * Created Date: Monday, November 14th 2022, 4:04:31 pm * Author: ccagml diff --git a/src/childProcessCall/cli.ts b/src/RemoteCall/cli.ts similarity index 97% rename from src/childProcessCall/cli.ts rename to src/RemoteCall/cli.ts index f23677d..f7923af 100644 --- a/src/childProcessCall/cli.ts +++ b/src/RemoteCall/cli.ts @@ -1,5 +1,5 @@ /* - * Filename: https://github.com/ccagml/vscode-leetcode-problem-rating/src/childProcessCall/cli.ts + * Filename: https://github.com/ccagml/vscode-leetcode-problem-rating/src/RemoteCall/cli.ts * Path: https://github.com/ccagml/vscode-leetcode-problem-rating * Created Date: Thursday, October 27th 2022, 7:43:29 pm * Author: ccagml diff --git a/src/childProcessCall/commUtils.ts b/src/RemoteCall/commUtils.ts similarity index 95% rename from src/childProcessCall/commUtils.ts rename to src/RemoteCall/commUtils.ts index 96e9a61..25724a3 100644 --- a/src/childProcessCall/commUtils.ts +++ b/src/RemoteCall/commUtils.ts @@ -1,5 +1,5 @@ /* - * Filename: /home/cc/vscode-leetcode-problem-rating/src/childProcessCall/commUtils.ts + * Filename: /home/cc/vscode-leetcode-problem-rating/src/RemoteCall/commUtils.ts * Path: /home/cc/vscode-leetcode-problem-rating * Created Date: Wednesday, November 16th 2022, 4:50:55 pm * Author: ccagml diff --git a/src/childProcessCall/config.ts b/src/RemoteCall/config.ts similarity index 99% rename from src/childProcessCall/config.ts rename to src/RemoteCall/config.ts index 15d5ce4..1e11532 100644 --- a/src/childProcessCall/config.ts +++ b/src/RemoteCall/config.ts @@ -1,5 +1,5 @@ /* - * Filename: https://github.com/ccagml/vscode-leetcode-problem-rating/src/childProcessCall/config.ts + * Filename: https://github.com/ccagml/vscode-leetcode-problem-rating/src/RemoteCall/config.ts * Path: https://github.com/ccagml/vscode-leetcode-problem-rating * Created Date: Thursday, October 27th 2022, 7:43:29 pm * Author: ccagml diff --git a/src/childProcessCall/factory/api/cache.ts b/src/RemoteCall/factory/api/cache.ts similarity index 92% rename from src/childProcessCall/factory/api/cache.ts rename to src/RemoteCall/factory/api/cache.ts index 03c9dca..4f3c57f 100644 --- a/src/childProcessCall/factory/api/cache.ts +++ b/src/RemoteCall/factory/api/cache.ts @@ -1,5 +1,5 @@ /* - * Filename: /home/cc/vscode-leetcode-problem-rating/src/childProcessCall/factory/api/cache.ts + * Filename: /home/cc/vscode-leetcode-problem-rating/src/RemoteCall/factory/api/cache.ts * Path: /home/cc/vscode-leetcode-problem-rating * Created Date: Monday, November 14th 2022, 4:04:31 pm * Author: ccagml diff --git a/src/childProcessCall/factory/api/list.ts b/src/RemoteCall/factory/api/list.ts similarity index 96% rename from src/childProcessCall/factory/api/list.ts rename to src/RemoteCall/factory/api/list.ts index 0e8997a..4bc0526 100644 --- a/src/childProcessCall/factory/api/list.ts +++ b/src/RemoteCall/factory/api/list.ts @@ -1,5 +1,5 @@ /* - * Filename: /home/cc/vscode-leetcode-problem-rating/src/childProcessCall/factory/api/list.ts + * Filename: /home/cc/vscode-leetcode-problem-rating/src/RemoteCall/factory/api/list.ts * Path: /home/cc/vscode-leetcode-problem-rating * Created Date: Monday, November 14th 2022, 4:04:31 pm * Author: ccagml diff --git a/src/childProcessCall/factory/api/plugin.ts b/src/RemoteCall/factory/api/plugin.ts similarity index 95% rename from src/childProcessCall/factory/api/plugin.ts rename to src/RemoteCall/factory/api/plugin.ts index 5e967bc..97ffe06 100644 --- a/src/childProcessCall/factory/api/plugin.ts +++ b/src/RemoteCall/factory/api/plugin.ts @@ -1,5 +1,5 @@ /* - * Filename: /home/cc/vscode-leetcode-problem-rating/src/childProcessCall/factory/api/plugin.ts + * Filename: /home/cc/vscode-leetcode-problem-rating/src/RemoteCall/factory/api/plugin.ts * Path: /home/cc/vscode-leetcode-problem-rating * Created Date: Monday, November 14th 2022, 4:04:31 pm * Author: ccagml diff --git a/src/childProcessCall/factory/api/query.ts b/src/RemoteCall/factory/api/query.ts similarity index 96% rename from src/childProcessCall/factory/api/query.ts rename to src/RemoteCall/factory/api/query.ts index 67a9cf7..31a1bc6 100644 --- a/src/childProcessCall/factory/api/query.ts +++ b/src/RemoteCall/factory/api/query.ts @@ -1,5 +1,5 @@ /* - * Filename: /home/cc/vscode-leetcode-problem-rating/src/childProcessCall/factory/api/query.ts + * Filename: /home/cc/vscode-leetcode-problem-rating/src/RemoteCall/factory/api/query.ts * Path: /home/cc/vscode-leetcode-problem-rating * Created Date: Monday, November 14th 2022, 4:04:31 pm * Author: ccagml diff --git a/src/childProcessCall/factory/api/show.ts b/src/RemoteCall/factory/api/show.ts similarity index 98% rename from src/childProcessCall/factory/api/show.ts rename to src/RemoteCall/factory/api/show.ts index 5d6e239..3a6324b 100644 --- a/src/childProcessCall/factory/api/show.ts +++ b/src/RemoteCall/factory/api/show.ts @@ -1,5 +1,5 @@ /* - * Filename: /home/cc/vscode-leetcode-problem-rating/src/childProcessCall/factory/api/show.ts + * Filename: /home/cc/vscode-leetcode-problem-rating/src/RemoteCall/factory/api/show.ts * Path: /home/cc/vscode-leetcode-problem-rating * Created Date: Monday, November 14th 2022, 4:04:31 pm * Author: ccagml diff --git a/src/childProcessCall/factory/api/star.ts b/src/RemoteCall/factory/api/star.ts similarity index 94% rename from src/childProcessCall/factory/api/star.ts rename to src/RemoteCall/factory/api/star.ts index 18c6748..14431ff 100644 --- a/src/childProcessCall/factory/api/star.ts +++ b/src/RemoteCall/factory/api/star.ts @@ -1,5 +1,5 @@ /* - * Filename: /home/cc/vscode-leetcode-problem-rating/src/childProcessCall/factory/api/star.ts + * Filename: /home/cc/vscode-leetcode-problem-rating/src/RemoteCall/factory/api/star.ts * Path: /home/cc/vscode-leetcode-problem-rating * Created Date: Monday, November 14th 2022, 4:04:31 pm * Author: ccagml diff --git a/src/childProcessCall/factory/api/submission.ts b/src/RemoteCall/factory/api/submission.ts similarity index 98% rename from src/childProcessCall/factory/api/submission.ts rename to src/RemoteCall/factory/api/submission.ts index d8b7dfa..a338d17 100644 --- a/src/childProcessCall/factory/api/submission.ts +++ b/src/RemoteCall/factory/api/submission.ts @@ -1,5 +1,5 @@ /* - * Filename: /home/cc/vscode-leetcode-problem-rating/src/childProcessCall/factory/api/submission.ts + * Filename: /home/cc/vscode-leetcode-problem-rating/src/RemoteCall/factory/api/submission.ts * Path: /home/cc/vscode-leetcode-problem-rating * Created Date: Monday, November 14th 2022, 4:04:31 pm * Author: ccagml diff --git a/src/childProcessCall/factory/api/submit.ts b/src/RemoteCall/factory/api/submit.ts similarity index 97% rename from src/childProcessCall/factory/api/submit.ts rename to src/RemoteCall/factory/api/submit.ts index 0dbdd32..2955385 100644 --- a/src/childProcessCall/factory/api/submit.ts +++ b/src/RemoteCall/factory/api/submit.ts @@ -1,5 +1,5 @@ /* - * Filename: /home/cc/vscode-leetcode-problem-rating/src/childProcessCall/factory/api/submit.ts + * Filename: /home/cc/vscode-leetcode-problem-rating/src/RemoteCall/factory/api/submit.ts * Path: /home/cc/vscode-leetcode-problem-rating * Created Date: Monday, November 14th 2022, 4:04:31 pm * Author: ccagml diff --git a/src/childProcessCall/factory/api/test.ts b/src/RemoteCall/factory/api/test.ts similarity index 98% rename from src/childProcessCall/factory/api/test.ts rename to src/RemoteCall/factory/api/test.ts index d702449..babc643 100644 --- a/src/childProcessCall/factory/api/test.ts +++ b/src/RemoteCall/factory/api/test.ts @@ -1,5 +1,5 @@ /* - * Filename: /home/cc/vscode-leetcode-problem-rating/src/childProcessCall/factory/api/test.ts + * Filename: /home/cc/vscode-leetcode-problem-rating/src/RemoteCall/factory/api/test.ts * Path: /home/cc/vscode-leetcode-problem-rating * Created Date: Wednesday, November 16th 2022, 3:13:59 pm * Author: ccagml diff --git a/src/childProcessCall/factory/api/user.ts b/src/RemoteCall/factory/api/user.ts similarity index 97% rename from src/childProcessCall/factory/api/user.ts rename to src/RemoteCall/factory/api/user.ts index 51df7d1..9f8a696 100644 --- a/src/childProcessCall/factory/api/user.ts +++ b/src/RemoteCall/factory/api/user.ts @@ -1,5 +1,5 @@ /* - * Filename: /home/cc/vscode-leetcode-problem-rating/src/childProcessCall/factory/api/user.ts + * Filename: /home/cc/vscode-leetcode-problem-rating/src/RemoteCall/factory/api/user.ts * Path: /home/cc/vscode-leetcode-problem-rating * Created Date: Monday, November 14th 2022, 4:04:31 pm * Author: ccagml diff --git a/src/childProcessCall/factory/apiFactory.ts b/src/RemoteCall/factory/apiFactory.ts similarity index 100% rename from src/childProcessCall/factory/apiFactory.ts rename to src/RemoteCall/factory/apiFactory.ts diff --git a/src/childProcessCall/factory/baseApi.ts b/src/RemoteCall/factory/baseApi.ts similarity index 100% rename from src/childProcessCall/factory/baseApi.ts rename to src/RemoteCall/factory/baseApi.ts diff --git a/src/childProcessCall/queue.ts b/src/RemoteCall/queue.ts similarity index 97% rename from src/childProcessCall/queue.ts rename to src/RemoteCall/queue.ts index 0488210..bc2f41a 100644 --- a/src/childProcessCall/queue.ts +++ b/src/RemoteCall/queue.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/RemoteCall/queue.ts * Path: https://github.com/ccagml/vscode-leetcode-problem-rating * Created Date: Thursday, October 27th 2022, 7:43:29 pm * Author: ccagml diff --git a/src/childProcessCall/session.ts b/src/RemoteCall/session.ts similarity index 98% rename from src/childProcessCall/session.ts rename to src/RemoteCall/session.ts index 7fc3412..6969e98 100644 --- a/src/childProcessCall/session.ts +++ b/src/RemoteCall/session.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/RemoteCall/session.ts * Path: https://github.com/ccagml/vscode-leetcode-problem-rating * Created Date: Thursday, October 27th 2022, 7:43:29 pm * Author: ccagml diff --git a/src/childProcessCall/storageUtils.ts b/src/RemoteCall/storageUtils.ts similarity index 99% rename from src/childProcessCall/storageUtils.ts rename to src/RemoteCall/storageUtils.ts index f25e93e..5afdf1d 100644 --- a/src/childProcessCall/storageUtils.ts +++ b/src/RemoteCall/storageUtils.ts @@ -1,5 +1,5 @@ /* - * Filename: https://github.com/ccagml/vscode-leetcode-problem-rating/src/childProcessCall/storageUtils.ts + * Filename: https://github.com/ccagml/vscode-leetcode-problem-rating/src/RemoteCall/storageUtils.ts * Path: https://github.com/ccagml/vscode-leetcode-problem-rating * Created Date: Thursday, October 27th 2022, 7:43:29 pm * Author: ccagml diff --git a/src/service/ExecuteService.ts b/src/service/ExecuteService.ts index eb7ab24..76c2d4c 100644 --- a/src/service/ExecuteService.ts +++ b/src/service/ExecuteService.ts @@ -39,7 +39,7 @@ class ExecuteService implements Disposable { private configurationChangeListener: Disposable; constructor() { - // this.leetCodeCliResourcesRootPath = path.join(__dirname, "..", "..", "node_modules", "childProcessCall"); + // this.leetCodeCliResourcesRootPath = path.join(__dirname, "..", "..", "node_modules", "RemoteCall"); if (!systemUtils.useVscodeNode()) { this.leetCodeCliResourcesRootPath = path.join( __dirname, @@ -56,7 +56,7 @@ class ExecuteService implements Disposable { "..", "out", "src", - "childProcessCall" + "RemoteCall" ); this.nodeExecutable = this.initNodePath(); this.configurationChangeListener = workspace.onDidChangeConfiguration( From 4b727dd2123957fd8f8d6f017523de50164267dc Mon Sep 17 00:00:00 2001 From: ccagml Date: Thu, 17 Nov 2022 12:01:37 +0800 Subject: [PATCH 11/26] update --- resources/bin/leetcode | 2 +- src/RemoteCall/actionChain/chain.ts | 8 +-- src/RemoteCall/actionChain/chainNode/cache.ts | 6 +- src/RemoteCall/actionChain/chainNode/core.ts | 5 +- .../actionChain/chainNode/leetcode.cn.ts | 23 ++++--- .../actionChain/chainNode/leetcode.ts | 68 +++++++++---------- src/RemoteCall/actionChain/chainNode/retry.ts | 8 +-- .../actionChain/chainNode/solution.discuss.ts | 4 +- src/RemoteCall/{cli.ts => childMain.ts} | 29 ++++---- src/RemoteCall/factory/api/cache.ts | 4 +- src/RemoteCall/factory/api/list.ts | 4 +- src/RemoteCall/factory/api/plugin.ts | 8 +-- src/RemoteCall/factory/api/query.ts | 4 +- src/RemoteCall/factory/api/show.ts | 16 ++--- src/RemoteCall/factory/api/star.ts | 4 +- src/RemoteCall/factory/api/submit.ts | 6 +- src/RemoteCall/factory/api/test.ts | 8 +-- src/RemoteCall/factory/api/user.ts | 4 +- .../{Reply.ts => utils/ReplyUtils.ts} | 0 src/RemoteCall/{ => utils}/commUtils.ts | 0 .../{config.ts => utils/configUtils.ts} | 2 +- .../{queue.ts => utils/queueUtils.ts} | 4 +- .../{session.ts => utils/sessionUtils.ts} | 4 +- src/RemoteCall/{ => utils}/storageUtils.ts | 2 +- src/service/ExecuteService.ts | 2 +- 25 files changed, 113 insertions(+), 112 deletions(-) rename src/RemoteCall/{cli.ts => childMain.ts} (60%) rename src/RemoteCall/{Reply.ts => utils/ReplyUtils.ts} (100%) rename src/RemoteCall/{ => utils}/commUtils.ts (100%) rename src/RemoteCall/{config.ts => utils/configUtils.ts} (98%) rename src/RemoteCall/{queue.ts => utils/queueUtils.ts} (92%) rename src/RemoteCall/{session.ts => utils/sessionUtils.ts} (94%) rename src/RemoteCall/{ => utils}/storageUtils.ts (99%) diff --git a/resources/bin/leetcode b/resources/bin/leetcode index f19b706..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/src/RemoteCall/actionChain/chain.ts b/src/RemoteCall/actionChain/chain.ts index 18f40ab..91eb55f 100644 --- a/src/RemoteCall/actionChain/chain.ts +++ b/src/RemoteCall/actionChain/chain.ts @@ -9,9 +9,9 @@ let underscore = require("underscore"); -import { config as out_config } from "../config"; -import { storageUtils } from "../storageUtils"; -import { commUtils } from "../commUtils"; +import { configUtils } from "../utils/configUtils"; +import { storageUtils } from "../utils/storageUtils"; +import { commUtils } from "../utils/commUtils"; export class Chain { id; @@ -39,7 +39,7 @@ export class Chain { } public init(): void { - this.config = out_config.plugins[this.name] || {}; + this.config = configUtils.plugins[this.name] || {}; this.next = null; } diff --git a/src/RemoteCall/actionChain/chainNode/cache.ts b/src/RemoteCall/actionChain/chainNode/cache.ts index 525b1fd..e8fa585 100644 --- a/src/RemoteCall/actionChain/chainNode/cache.ts +++ b/src/RemoteCall/actionChain/chainNode/cache.ts @@ -11,9 +11,9 @@ import { Chain } from "../chain"; let underscore = require("underscore"); -import { storageUtils } from "../../storageUtils"; -import { commUtils } from "../../commUtils"; -import { session } from "../../session"; +import { storageUtils } from "../../utils/storageUtils"; +import { commUtils } from "../../utils/commUtils"; +import { session } from "../../utils/sessionUtils"; class CachePlugin extends Chain { id = 50; diff --git a/src/RemoteCall/actionChain/chainNode/core.ts b/src/RemoteCall/actionChain/chainNode/core.ts index 12c4c2d..b82dcb8 100644 --- a/src/RemoteCall/actionChain/chainNode/core.ts +++ b/src/RemoteCall/actionChain/chainNode/core.ts @@ -12,7 +12,8 @@ let util = require("util"); let _ = require("underscore"); let cheerio = require("cheerio"); -import { storageUtils } from "../../storageUtils"; +import { storageUtils } from "../../utils/storageUtils"; +import { configUtils } from "../../utils/configUtils"; import { Chain } from "../chain"; @@ -89,7 +90,7 @@ class CorePlugin extends Chain { // 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"); diff --git a/src/RemoteCall/actionChain/chainNode/leetcode.cn.ts b/src/RemoteCall/actionChain/chainNode/leetcode.cn.ts index ec3d494..d8a06b1 100644 --- a/src/RemoteCall/actionChain/chainNode/leetcode.cn.ts +++ b/src/RemoteCall/actionChain/chainNode/leetcode.cn.ts @@ -11,9 +11,9 @@ import { Chain } from "./../chain"; let request = require("request"); -import { config } from "../../config"; +import { configUtils } from "../../utils/configUtils"; -import { session } from "../../session"; +import { session } from "../../utils/sessionUtils"; class LeetCodeCn extends Chain { id = 15; @@ -23,7 +23,7 @@ class LeetCodeCn extends Chain { super(); } init() { - config.fix_cn(); + configUtils.fix_cn(); } getProblems = (needTranslation, cb) => { @@ -50,8 +50,8 @@ class LeetCodeCn extends Chain { }; getProblemsTitle = (cb) => { - const opts = makeOpts(config.sys.urls.graphql); - opts.headers.Origin = config.sys.urls.base; + 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; @@ -83,8 +83,8 @@ class LeetCodeCn extends Chain { }; getQuestionOfToday = (cb) => { - const opts = makeOpts(config.sys.urls.graphql); - opts.headers.Origin = config.sys.urls.base; + const opts = makeOpts(configUtils.sys.urls.graphql); + opts.headers.Origin = configUtils.sys.urls.base; opts.headers.Referer = "https://leetcode.cn/"; opts.json = true; @@ -130,9 +130,12 @@ class LeetCodeCn extends Chain { }); }; 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 = { diff --git a/src/RemoteCall/actionChain/chainNode/leetcode.ts b/src/RemoteCall/actionChain/chainNode/leetcode.ts index 7d6325c..d8bb929 100644 --- a/src/RemoteCall/actionChain/chainNode/leetcode.ts +++ b/src/RemoteCall/actionChain/chainNode/leetcode.ts @@ -13,13 +13,13 @@ let underscore = require("underscore"); let request = require("request"); let prompt_out = require("prompt"); -import { config } from "../../config"; -import { commUtils } from "../../commUtils"; -import { storageUtils } from "../../storageUtils"; -import { reply } from "../../Reply"; -import { session } from "../../session"; +import { configUtils } from "../../utils/configUtils"; +import { commUtils } from "../../utils/commUtils"; +import { storageUtils } from "../../utils/storageUtils"; +import { reply } from "../../utils/ReplyUtils"; +import { session } from "../../utils/sessionUtils"; import { Chain } from "./../chain"; -import { Queue } from "../../queue"; +import { Queue } from "../../utils/queueUtils"; class LeetCode extends Chain { id = 10; @@ -63,7 +63,7 @@ class LeetCode extends Chain { } init() { - config.app = "leetcode"; + configUtils.app = "leetcode"; } getProblems = (_, cb) => { @@ -80,7 +80,7 @@ class LeetCode extends Chain { }); }; - 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); }); @@ -88,7 +88,7 @@ class LeetCode extends Chain { getCategoryProblems = (category, cb) => { const opts = this.makeOpts( - config.sys.urls.problems.replace("$category", category) + configUtils.sys.urls.problems.replace("$category", category) ); let that = this; @@ -111,7 +111,7 @@ class LeetCode extends Chain { fid: p.stat.frontend_question_id, name: p.stat.question__title, slug: p.stat.question__title_slug, - link: config.sys.urls.problem.replace( + link: configUtils.sys.urls.problem.replace( "$slug", p.stat.question__title_slug ), @@ -132,8 +132,8 @@ class LeetCode extends Chain { 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; @@ -187,10 +187,10 @@ class LeetCode extends Chain { }; runCode = (opts, problem, cb) => { opts.method = "POST"; - opts.headers.Origin = config.sys.urls.base; + 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, { @@ -224,7 +224,7 @@ class LeetCode extends Chain { verifyResult = (task, queue, cb) => { const opts = queue.ctx.opts; opts.method = "GET"; - opts.url = config.sys.urls.verify.replace("$id", task.id); + opts.url = configUtils.sys.urls.verify.replace("$id", task.id); let that = this; request(opts, function (e, resp, body) { @@ -290,7 +290,7 @@ class LeetCode extends Chain { testProblem = (problem, cb) => { const opts = this.makeOpts( - config.sys.urls.test.replace("$slug", problem.slug) + configUtils.sys.urls.test.replace("$slug", problem.slug) ); opts.body = { data_input: problem.testcase }; let that = this; @@ -316,7 +316,7 @@ class LeetCode extends Chain { submitProblem = (problem, cb) => { const opts = this.makeOpts( - config.sys.urls.submit.replace("$slug", problem.slug) + configUtils.sys.urls.submit.replace("$slug", problem.slug) ); opts.body = { judge_type: "large" }; let that = this; @@ -337,9 +337,9 @@ class LeetCode extends Chain { getSubmissions = (problem, cb) => { const opts = this.makeOpts( - config.sys.urls.submissions.replace("$slug", problem.slug) + configUtils.sys.urls.submissions.replace("$slug", problem.slug) ); - opts.headers.Referer = config.sys.urls.problem.replace( + opts.headers.Referer = configUtils.sys.urls.problem.replace( "$slug", problem.slug ); @@ -361,7 +361,7 @@ class LeetCode extends Chain { getSubmission = (submission, cb) => { const opts = this.makeOpts( - config.sys.urls.submission.replace("$id", submission.id) + configUtils.sys.urls.submission.replace("$id", submission.id) ); let that = this; request(opts, function (e, resp, body) { @@ -382,8 +382,8 @@ class LeetCode extends Chain { const operationName = starred ? "addQuestionToFavorite" : "removeQuestionFromFavorite"; - 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; @@ -403,7 +403,7 @@ class LeetCode extends Chain { }; getFavorites = (cb: any) => { - const opts = this.makeOpts(config.sys.urls.favorites); + const opts = this.makeOpts(configUtils.sys.urls.favorites); let that = this; request(opts, function (e, resp, body) { @@ -417,9 +417,9 @@ class LeetCode extends Chain { 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: [ @@ -443,7 +443,7 @@ class LeetCode extends Chain { }; runSession = (method: any, data: any, cb: any) => { - const opts = this.makeOpts(config.sys.urls.session); + const opts = this.makeOpts(configUtils.sys.urls.session); opts.json = true; opts.method = method; opts.body = data; @@ -479,15 +479,15 @@ class LeetCode extends Chain { signin = (user: any, cb: any) => { let that = this; // eslint-disable-next-line @typescript-eslint/no-unused-vars - request(config.sys.urls.login, function (e: any, resp: any, _) { + request(configUtils.sys.urls.login, function (e: any, resp: any, _) { e = that.checkError(e, resp, 200); if (e) return cb(e); 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, + Origin: configUtils.sys.urls.base, + Referer: configUtils.sys.urls.login, Cookie: "csrftoken=" + user.loginCSRF + ";", }, form: { @@ -564,7 +564,7 @@ class LeetCode extends Chain { // 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) { + 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); @@ -584,7 +584,7 @@ class LeetCode extends Chain { }; 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; @@ -681,7 +681,7 @@ class LeetCode extends Chain { }; linkedinLogin = (user, cb) => { - const urls = config.sys.urls; + const urls = configUtils.sys.urls; const leetcodeUrl = urls.linkedin_login; const _request = request.defaults({ jar: true, diff --git a/src/RemoteCall/actionChain/chainNode/retry.ts b/src/RemoteCall/actionChain/chainNode/retry.ts index 56a384b..16c3178 100644 --- a/src/RemoteCall/actionChain/chainNode/retry.ts +++ b/src/RemoteCall/actionChain/chainNode/retry.ts @@ -8,8 +8,8 @@ */ import { Chain } from "./../chain"; -import { config } from "../../config"; -import { session } from "../../session"; +import { configUtils } from "../../utils/configUtils"; +import { session } from "../../utils/sessionUtils"; class RetryPlugin extends Chain { id = 30; @@ -19,9 +19,9 @@ class RetryPlugin extends Chain { canRetry = (e, name) => { return ( - config.autologin.enable && + configUtils.autologin.enable && e === session.errors.EXPIRED && - (this.count[name] || 0) < config.autologin.retry + (this.count[name] || 0) < configUtils.autologin.retry ); }; init = () => { diff --git a/src/RemoteCall/actionChain/chainNode/solution.discuss.ts b/src/RemoteCall/actionChain/chainNode/solution.discuss.ts index 9f599ea..1f384e0 100644 --- a/src/RemoteCall/actionChain/chainNode/solution.discuss.ts +++ b/src/RemoteCall/actionChain/chainNode/solution.discuss.ts @@ -9,8 +9,8 @@ let request = require("request"); -import { reply } from "../../Reply"; -import { session } from "../../session"; +import { reply } from "../../utils/ReplyUtils"; +import { session } from "../../utils/sessionUtils"; import { Chain } from "./../chain"; class SolutionDiscuss extends Chain { diff --git a/src/RemoteCall/cli.ts b/src/RemoteCall/childMain.ts similarity index 60% rename from src/RemoteCall/cli.ts rename to src/RemoteCall/childMain.ts index f7923af..283d2fc 100644 --- a/src/RemoteCall/cli.ts +++ b/src/RemoteCall/childMain.ts @@ -9,36 +9,33 @@ import { chain } from "./actionChain/chain"; import { corePlugin } from "./actionChain/chainNode/core"; -import { config } from "./config"; -import { reply } from "./Reply"; -import { storageUtils } from "./storageUtils"; +import { configUtils } from "./utils/configUtils"; +import { reply } from "./utils/ReplyUtils"; +import { storageUtils } from "./utils/storageUtils"; import { apiFactory } from "./factory/apiFactory"; import { IApi } from "./factory/baseApi"; -class NewCli { +class Main { constructor() { - this.run(); + this.exec(); } - public run() { + public exec() { process.stdout.on("error", function (e) { if (e.code === "EPIPE") process.exit(); }); - config.init(JSON.parse(process.env.ccagml || "{}")); + configUtils.init(JSON.parse(process.env.ccagml || "{}")); reply.init(); storageUtils.init(); if (chain.base_init(corePlugin)) { chain.save(); storageUtils.initCache(); - this.doApi(); - } - } - private doApi() { - let com_str = process.argv[2]; - let curApi: IApi | undefined = apiFactory.getApi(com_str); - if (curApi != undefined) { - curApi.call(curApi.callArg(process.argv)); + let com_str = process.argv[2]; + let curApi: IApi | undefined = apiFactory.getApi(com_str); + if (curApi != undefined) { + curApi.call(curApi.callArg(process.argv)); + } } } } -export const newCli: NewCli = new NewCli(); +export const main: Main = new Main(); diff --git a/src/RemoteCall/factory/api/cache.ts b/src/RemoteCall/factory/api/cache.ts index 4f3c57f..48674e7 100644 --- a/src/RemoteCall/factory/api/cache.ts +++ b/src/RemoteCall/factory/api/cache.ts @@ -7,8 +7,8 @@ * Copyright (c) 2022 ccagml . All rights reserved. */ -import { storageUtils } from "../../storageUtils"; -import { session } from "../../session"; +import { storageUtils } from "../../utils/storageUtils"; +import { session } from "../../utils/sessionUtils"; import { ApiBase } from "../baseApi"; class CacheApi extends ApiBase { diff --git a/src/RemoteCall/factory/api/list.ts b/src/RemoteCall/factory/api/list.ts index 4bc0526..fb7daa8 100644 --- a/src/RemoteCall/factory/api/list.ts +++ b/src/RemoteCall/factory/api/list.ts @@ -7,8 +7,8 @@ * Copyright (c) 2022 ccagml . All rights reserved. */ -import { reply } from "../../Reply"; -import { session } from "../../session"; +import { reply } from "../../utils/ReplyUtils"; +import { session } from "../../utils/sessionUtils"; import { ApiBase } from "../baseApi"; import { chain } from "../../actionChain/chain"; diff --git a/src/RemoteCall/factory/api/plugin.ts b/src/RemoteCall/factory/api/plugin.ts index 97ffe06..898ed20 100644 --- a/src/RemoteCall/factory/api/plugin.ts +++ b/src/RemoteCall/factory/api/plugin.ts @@ -7,10 +7,10 @@ * Copyright (c) 2022 ccagml . All rights reserved. */ -import { config } from "../../config"; -import { reply } from "../../Reply"; +import { configUtils } from "../../utils/configUtils"; +import { reply } from "../../utils/ReplyUtils"; import { chain } from "../../actionChain/chain"; -import { session } from "../../session"; +import { session } from "../../utils/sessionUtils"; import { ApiBase } from "../baseApi"; class PluginApi extends ApiBase { @@ -85,7 +85,7 @@ class PluginApi extends ApiBase { p.save(); chain.init(); } else if (argv.config) { - reply.info(JSON.stringify(config.plugins[name] || {}, null, 2)); + reply.info(JSON.stringify(configUtils.plugins[name] || {}, null, 2)); } } } diff --git a/src/RemoteCall/factory/api/query.ts b/src/RemoteCall/factory/api/query.ts index 31a1bc6..d1b78d7 100644 --- a/src/RemoteCall/factory/api/query.ts +++ b/src/RemoteCall/factory/api/query.ts @@ -7,8 +7,8 @@ * Copyright (c) 2022 ccagml . All rights reserved. */ -import { reply } from "../../Reply"; -import { session } from "../../session"; +import { reply } from "../../utils/ReplyUtils"; +import { session } from "../../utils/sessionUtils"; import { ApiBase } from "../baseApi"; import { chain } from "../../actionChain/chain"; diff --git a/src/RemoteCall/factory/api/show.ts b/src/RemoteCall/factory/api/show.ts index 3a6324b..32f4d8b 100644 --- a/src/RemoteCall/factory/api/show.ts +++ b/src/RemoteCall/factory/api/show.ts @@ -10,12 +10,12 @@ let util = require("util"); let childProcess = require("child_process"); -import { storageUtils } from "../../storageUtils"; +import { storageUtils } from "../../utils/storageUtils"; -import { reply } from "../../Reply"; -import { config } from "../../config"; +import { reply } from "../../utils/ReplyUtils"; +import { configUtils } from "../../utils/configUtils"; -import { session } from "../../session"; +import { session } from "../../utils/sessionUtils"; import { ApiBase } from "../baseApi"; import { chain } from "../../actionChain/chain"; @@ -46,9 +46,9 @@ class ShowApi extends ApiBase { .option("l", { alias: "lang", type: "string", - default: config.code.lang, + default: configUtils.code.lang, describe: "Programming language of the source code", - choices: config.sys.langs, + choices: configUtils.sys.langs, }) .option("o", { alias: "outdir", @@ -100,7 +100,7 @@ class ShowApi extends ApiBase { genFileName(problem, opts) { const path = require("path"); const params = [ - storageUtils.fmt(config.file.show, problem), + storageUtils.fmt(configUtils.file.show, problem), "", storageUtils.getFileExtByLanguage(opts.lang), ]; @@ -152,7 +152,7 @@ class ShowApi extends ApiBase { storageUtils.write(filename, code); if (argv.editor !== undefined) { - childProcess.spawn(argv.editor || config.code.editor, [filename], { + childProcess.spawn(argv.editor || configUtils.code.editor, [filename], { // in case your editor of choice is vim or emacs stdio: "inherit", }); diff --git a/src/RemoteCall/factory/api/star.ts b/src/RemoteCall/factory/api/star.ts index 14431ff..5f3fea2 100644 --- a/src/RemoteCall/factory/api/star.ts +++ b/src/RemoteCall/factory/api/star.ts @@ -7,9 +7,9 @@ * Copyright (c) 2022 ccagml . All rights reserved. */ -import { reply } from "../../Reply"; +import { reply } from "../../utils/ReplyUtils"; -import { session } from "../../session"; +import { session } from "../../utils/sessionUtils"; import { ApiBase } from "../baseApi"; import { chain } from "../../actionChain/chain"; diff --git a/src/RemoteCall/factory/api/submit.ts b/src/RemoteCall/factory/api/submit.ts index 2955385..119080c 100644 --- a/src/RemoteCall/factory/api/submit.ts +++ b/src/RemoteCall/factory/api/submit.ts @@ -10,10 +10,10 @@ let util = require("util"); let lodash = require("lodash"); -import { storageUtils } from "../../storageUtils"; -import { reply } from "../../Reply"; +import { storageUtils } from "../../utils/storageUtils"; +import { reply } from "../../utils/ReplyUtils"; -import { session } from "../../session"; +import { session } from "../../utils/sessionUtils"; import { ApiBase } from "../baseApi"; import { chain } from "../../actionChain/chain"; diff --git a/src/RemoteCall/factory/api/test.ts b/src/RemoteCall/factory/api/test.ts index babc643..2cff296 100644 --- a/src/RemoteCall/factory/api/test.ts +++ b/src/RemoteCall/factory/api/test.ts @@ -10,12 +10,12 @@ let _ = require("underscore"); let lodash = require("lodash"); -import { storageUtils } from "../../storageUtils"; -import { reply } from "../../Reply"; +import { storageUtils } from "../../utils/storageUtils"; +import { reply } from "../../utils/ReplyUtils"; -import { session } from "../../session"; +import { session } from "../../utils/sessionUtils"; import { ApiBase } from "../baseApi"; -import { commUtils } from "../../commUtils"; +import { commUtils } from "../../utils/commUtils"; import { chain } from "../../actionChain/chain"; class TestApi extends ApiBase { diff --git a/src/RemoteCall/factory/api/user.ts b/src/RemoteCall/factory/api/user.ts index 9f8a696..76be8f9 100644 --- a/src/RemoteCall/factory/api/user.ts +++ b/src/RemoteCall/factory/api/user.ts @@ -9,9 +9,9 @@ let prompt_out = require("prompt"); -import { reply } from "../../Reply"; +import { reply } from "../../utils/ReplyUtils"; -import { session } from "../../session"; +import { session } from "../../utils/sessionUtils"; import { ApiBase } from "../baseApi"; import { chain } from "../../actionChain/chain"; diff --git a/src/RemoteCall/Reply.ts b/src/RemoteCall/utils/ReplyUtils.ts similarity index 100% rename from src/RemoteCall/Reply.ts rename to src/RemoteCall/utils/ReplyUtils.ts diff --git a/src/RemoteCall/commUtils.ts b/src/RemoteCall/utils/commUtils.ts similarity index 100% rename from src/RemoteCall/commUtils.ts rename to src/RemoteCall/utils/commUtils.ts diff --git a/src/RemoteCall/config.ts b/src/RemoteCall/utils/configUtils.ts similarity index 98% rename from src/RemoteCall/config.ts rename to src/RemoteCall/utils/configUtils.ts index 1e11532..b8d2a37 100644 --- a/src/RemoteCall/config.ts +++ b/src/RemoteCall/utils/configUtils.ts @@ -144,4 +144,4 @@ class Config { } } -export const config: Config = new Config(); +export const configUtils: Config = new Config(); diff --git a/src/RemoteCall/queue.ts b/src/RemoteCall/utils/queueUtils.ts similarity index 92% rename from src/RemoteCall/queue.ts rename to src/RemoteCall/utils/queueUtils.ts index bc2f41a..07775aa 100644 --- a/src/RemoteCall/queue.ts +++ b/src/RemoteCall/utils/queueUtils.ts @@ -9,7 +9,7 @@ let underscore = require("underscore"); -import { config } from "./config"; +import { configUtils } from "./configUtils"; export class Queue { tasks; @@ -36,7 +36,7 @@ export class Queue { } run(concurrency?, onDone?) { - this.concurrency = concurrency || config.network.concurrency || 1; + this.concurrency = concurrency || configUtils.network.concurrency || 1; this.onDone = onDone; const self = this; diff --git a/src/RemoteCall/session.ts b/src/RemoteCall/utils/sessionUtils.ts similarity index 94% rename from src/RemoteCall/session.ts rename to src/RemoteCall/utils/sessionUtils.ts index 6969e98..87ddf66 100644 --- a/src/RemoteCall/session.ts +++ b/src/RemoteCall/utils/sessionUtils.ts @@ -11,7 +11,7 @@ let moment_out = require("moment"); let underscore = require("underscore"); import { storageUtils } from "./storageUtils"; -import { config } from "./config"; +import { configUtils } from "./configUtils"; import { commUtils } from "./commUtils"; class Session { @@ -32,7 +32,7 @@ class Session { // otherwise don't dump password for the sake of security. const _user = underscore.omit( user, - config.autologin.enable ? [] : ["pass"] + configUtils.autologin.enable ? [] : ["pass"] ); storageUtils.setCache(commUtils.KEYS.user, _user); }; diff --git a/src/RemoteCall/storageUtils.ts b/src/RemoteCall/utils/storageUtils.ts similarity index 99% rename from src/RemoteCall/storageUtils.ts rename to src/RemoteCall/utils/storageUtils.ts index 5afdf1d..aa0550d 100644 --- a/src/RemoteCall/storageUtils.ts +++ b/src/RemoteCall/utils/storageUtils.ts @@ -181,7 +181,7 @@ class StorageUtils { } public appDir() { - const config = require("./config"); + const config = require("./configUtils"); return path.join(this.homeDir(), config.app || "leetcode"); } diff --git a/src/service/ExecuteService.ts b/src/service/ExecuteService.ts index 76c2d4c..070450b 100644 --- a/src/service/ExecuteService.ts +++ b/src/service/ExecuteService.ts @@ -71,7 +71,7 @@ class ExecuteService implements Disposable { public async getLeetCodeBinaryPath(): Promise { if (systemUtils.useVscodeNode()) { - return `${path.join(this.leetCodeCliRootPath, "cli.js")}`; + return `${path.join(this.leetCodeCliRootPath, "childMain.js")}`; } else { if (systemUtils.useWsl()) { return `${await systemUtils.toWslPath( From 4a3c9b24e35b9128a44f36a92491979594384d25 Mon Sep 17 00:00:00 2001 From: ccagml Date: Thu, 17 Nov 2022 13:41:51 +0800 Subject: [PATCH 12/26] sessionUtils --- src/RemoteCall/actionChain/chain.ts | 2 +- src/RemoteCall/actionChain/chainNode/cache.ts | 10 ++++----- .../actionChain/chainNode/leetcode.cn.ts | 6 ++--- .../actionChain/chainNode/leetcode.ts | 22 +++++++++---------- src/RemoteCall/actionChain/chainNode/retry.ts | 6 ++--- .../actionChain/chainNode/solution.discuss.ts | 6 ++--- src/RemoteCall/factory/api/cache.ts | 4 ++-- src/RemoteCall/factory/api/list.ts | 4 ++-- src/RemoteCall/factory/api/plugin.ts | 4 ++-- src/RemoteCall/factory/api/query.ts | 4 ++-- src/RemoteCall/factory/api/show.ts | 4 ++-- src/RemoteCall/factory/api/star.ts | 4 ++-- src/RemoteCall/factory/api/submission.ts | 2 +- src/RemoteCall/factory/api/submit.ts | 8 +++---- src/RemoteCall/factory/api/test.ts | 4 ++-- src/RemoteCall/factory/api/user.ts | 6 ++--- src/RemoteCall/utils/sessionUtils.ts | 2 +- 17 files changed, 49 insertions(+), 49 deletions(-) diff --git a/src/RemoteCall/actionChain/chain.ts b/src/RemoteCall/actionChain/chain.ts index 91eb55f..3ef2f70 100644 --- a/src/RemoteCall/actionChain/chain.ts +++ b/src/RemoteCall/actionChain/chain.ts @@ -51,7 +51,7 @@ export class Chain { this.head = head; const stats = storageUtils.getCache(commUtils.KEYS.plugins) || {}; let file_plugin: Array = storageUtils.listCodeDir( - "actionChain/chainNode" + "../actionChain/chainNode" ); this.installed = []; for (let f of file_plugin) { diff --git a/src/RemoteCall/actionChain/chainNode/cache.ts b/src/RemoteCall/actionChain/chainNode/cache.ts index e8fa585..92517de 100644 --- a/src/RemoteCall/actionChain/chainNode/cache.ts +++ b/src/RemoteCall/actionChain/chainNode/cache.ts @@ -13,7 +13,7 @@ let underscore = require("underscore"); import { storageUtils } from "../../utils/storageUtils"; import { commUtils } from "../../utils/commUtils"; -import { session } from "../../utils/sessionUtils"; +import { sessionUtils } from "../../utils/sessionUtils"; class CachePlugin extends Chain { id = 50; @@ -113,16 +113,16 @@ class CachePlugin extends Chain { this.logout(user, false); this.next.login(user, function (e, user) { if (e) return cb(e); - session.saveUser(user); + sessionUtils.saveUser(user); return cb(null, user); }); }; logout = (user, purge) => { - if (!user) user = session.getUser(); - if (purge) session.deleteUser(); + if (!user) user = sessionUtils.getUser(); + if (purge) sessionUtils.deleteUser(); // NOTE: need invalidate any user related cache - session.deleteCodingSession(); + sessionUtils.deleteCodingSession(); return user; }; } diff --git a/src/RemoteCall/actionChain/chainNode/leetcode.cn.ts b/src/RemoteCall/actionChain/chainNode/leetcode.cn.ts index d8a06b1..7a9d065 100644 --- a/src/RemoteCall/actionChain/chainNode/leetcode.cn.ts +++ b/src/RemoteCall/actionChain/chainNode/leetcode.cn.ts @@ -13,7 +13,7 @@ let request = require("request"); import { configUtils } from "../../utils/configUtils"; -import { session } from "../../utils/sessionUtils"; +import { sessionUtils } from "../../utils/sessionUtils"; class LeetCodeCn extends Chain { id = 15; @@ -222,7 +222,7 @@ function makeOpts(url: any) { opts.url = url; opts.headers = {}; - if (session.isLogin()) signOpts(opts, session.getUser()); + if (sessionUtils.isLogin()) signOpts(opts, sessionUtils.getUser()); return opts; } @@ -231,7 +231,7 @@ function checkError(e: any, resp: any, expectedStatus: any) { const code = resp.statusCode; if (code === 403 || code === 401) { - e = session.errors.EXPIRED; + e = sessionUtils.errors.EXPIRED; } else { e = { msg: "http error", statusCode: code }; } diff --git a/src/RemoteCall/actionChain/chainNode/leetcode.ts b/src/RemoteCall/actionChain/chainNode/leetcode.ts index d8bb929..e4cd270 100644 --- a/src/RemoteCall/actionChain/chainNode/leetcode.ts +++ b/src/RemoteCall/actionChain/chainNode/leetcode.ts @@ -17,7 +17,7 @@ import { configUtils } from "../../utils/configUtils"; import { commUtils } from "../../utils/commUtils"; import { storageUtils } from "../../utils/storageUtils"; import { reply } from "../../utils/ReplyUtils"; -import { session } from "../../utils/sessionUtils"; +import { sessionUtils } from "../../utils/sessionUtils"; import { Chain } from "./../chain"; import { Queue } from "../../utils/queueUtils"; @@ -45,7 +45,7 @@ class LeetCode extends Chain { opts.url = url; opts.headers = {}; - if (session.isLogin()) this.signOpts(opts, session.getUser()); + if (sessionUtils.isLogin()) this.signOpts(opts, sessionUtils.getUser()); return opts; } @@ -54,7 +54,7 @@ class LeetCode extends Chain { const code = resp.statusCode; if (code === 403 || code === 401) { - e = session.errors.EXPIRED; + e = sessionUtils.errors.EXPIRED; } else { e = { msg: "http error", statusCode: code }; } @@ -99,7 +99,7 @@ class LeetCode extends Chain { 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 @@ -128,7 +128,7 @@ class LeetCode extends Chain { }; getProblem = (problem, needTranslation, cb) => { - const user = session.getUser(); + const user = sessionUtils.getUser(); if (problem.locked && !user.paid) return cb("failed to load locked problem!"); @@ -378,7 +378,7 @@ class LeetCode extends Chain { }; starProblem = (problem, starred, cb) => { - const user = session.getUser(); + const user = sessionUtils.getUser(); const operationName = starred ? "addQuestionToFavorite" : "removeQuestionFromFavorite"; @@ -451,7 +451,7 @@ class LeetCode extends Chain { 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); }); @@ -503,7 +503,7 @@ class LeetCode extends Chain { user.sessionCSRF = commUtils.getSetCookieValue(resp, "csrftoken"); user.sessionId = commUtils.getSetCookieValue(resp, "LEETCODE_SESSION"); - session.saveUser(user); + sessionUtils.saveUser(user); return cb(null, user); }); }); @@ -531,7 +531,7 @@ class LeetCode extends Chain { user.paid = _user.isCurrentUserPremium; user.name = _user.username; } - session.saveUser(user); + sessionUtils.saveUser(user); return cb(null, user); }); }); @@ -570,7 +570,7 @@ class LeetCode extends Chain { 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); }); }; @@ -579,7 +579,7 @@ class LeetCode extends Chain { 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); }; diff --git a/src/RemoteCall/actionChain/chainNode/retry.ts b/src/RemoteCall/actionChain/chainNode/retry.ts index 16c3178..02c9549 100644 --- a/src/RemoteCall/actionChain/chainNode/retry.ts +++ b/src/RemoteCall/actionChain/chainNode/retry.ts @@ -9,7 +9,7 @@ import { Chain } from "./../chain"; import { configUtils } from "../../utils/configUtils"; -import { session } from "../../utils/sessionUtils"; +import { sessionUtils } from "../../utils/sessionUtils"; class RetryPlugin extends Chain { id = 30; @@ -20,7 +20,7 @@ class RetryPlugin extends Chain { canRetry = (e, name) => { return ( configUtils.autologin.enable && - e === session.errors.EXPIRED && + e === sessionUtils.errors.EXPIRED && (this.count[name] || 0) < configUtils.autologin.retry ); }; @@ -72,7 +72,7 @@ class RetryPlugin extends Chain { // 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(); } diff --git a/src/RemoteCall/actionChain/chainNode/solution.discuss.ts b/src/RemoteCall/actionChain/chainNode/solution.discuss.ts index 1f384e0..3bc8225 100644 --- a/src/RemoteCall/actionChain/chainNode/solution.discuss.ts +++ b/src/RemoteCall/actionChain/chainNode/solution.discuss.ts @@ -10,7 +10,7 @@ let request = require("request"); import { reply } from "../../utils/ReplyUtils"; -import { session } from "../../utils/sessionUtils"; +import { sessionUtils } from "../../utils/sessionUtils"; import { Chain } from "./../chain"; class SolutionDiscuss extends Chain { @@ -23,9 +23,9 @@ class SolutionDiscuss extends Chain { getProblem = (problem, needTranslation, cb) => { this.next.getProblem(problem, needTranslation, function (e, problem) { - if (e || !session.argv.solution) return cb(e, problem); + if (e || !sessionUtils.argv.solution) return cb(e, problem); - let lang = session.argv.lang; + 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); diff --git a/src/RemoteCall/factory/api/cache.ts b/src/RemoteCall/factory/api/cache.ts index 48674e7..0292c85 100644 --- a/src/RemoteCall/factory/api/cache.ts +++ b/src/RemoteCall/factory/api/cache.ts @@ -8,7 +8,7 @@ */ import { storageUtils } from "../../utils/storageUtils"; -import { session } from "../../utils/sessionUtils"; +import { sessionUtils } from "../../utils/sessionUtils"; import { ApiBase } from "../baseApi"; class CacheApi extends ApiBase { @@ -29,7 +29,7 @@ class CacheApi extends ApiBase { } call(argv) { - session.argv = argv; + sessionUtils.argv = argv; const name = argv.keyword || ""; const isInteger = Number.isInteger(Number(name)); diff --git a/src/RemoteCall/factory/api/list.ts b/src/RemoteCall/factory/api/list.ts index fb7daa8..308f1b8 100644 --- a/src/RemoteCall/factory/api/list.ts +++ b/src/RemoteCall/factory/api/list.ts @@ -8,7 +8,7 @@ */ import { reply } from "../../utils/ReplyUtils"; -import { session } from "../../utils/sessionUtils"; +import { sessionUtils } from "../../utils/sessionUtils"; import { ApiBase } from "../baseApi"; import { chain } from "../../actionChain/chain"; @@ -70,7 +70,7 @@ class ListApi extends ApiBase { } call(argv) { - session.argv = argv; + sessionUtils.argv = argv; chain.getChainHead().filterProblems(argv, function (e, problems) { if (e) return reply.info(e); let new_objcet: Array = []; diff --git a/src/RemoteCall/factory/api/plugin.ts b/src/RemoteCall/factory/api/plugin.ts index 898ed20..673c325 100644 --- a/src/RemoteCall/factory/api/plugin.ts +++ b/src/RemoteCall/factory/api/plugin.ts @@ -10,7 +10,7 @@ import { configUtils } from "../../utils/configUtils"; import { reply } from "../../utils/ReplyUtils"; import { chain } from "../../actionChain/chain"; -import { session } from "../../utils/sessionUtils"; +import { sessionUtils } from "../../utils/sessionUtils"; import { ApiBase } from "../baseApi"; class PluginApi extends ApiBase { @@ -50,7 +50,7 @@ class PluginApi extends ApiBase { } call(argv) { - session.argv = argv; + sessionUtils.argv = argv; let all_plugin = chain.installed; const name = argv.name; diff --git a/src/RemoteCall/factory/api/query.ts b/src/RemoteCall/factory/api/query.ts index d1b78d7..ed4cffb 100644 --- a/src/RemoteCall/factory/api/query.ts +++ b/src/RemoteCall/factory/api/query.ts @@ -8,7 +8,7 @@ */ import { reply } from "../../utils/ReplyUtils"; -import { session } from "../../utils/sessionUtils"; +import { sessionUtils } from "../../utils/sessionUtils"; import { ApiBase } from "../baseApi"; import { chain } from "../../actionChain/chain"; @@ -54,7 +54,7 @@ class QueryApi extends ApiBase { } call(argv) { - session.argv = argv; + sessionUtils.argv = argv; if (argv.a) { chain.getChainHead().getTodayQuestion(function (e, result) { if (e) return; diff --git a/src/RemoteCall/factory/api/show.ts b/src/RemoteCall/factory/api/show.ts index 32f4d8b..151f94c 100644 --- a/src/RemoteCall/factory/api/show.ts +++ b/src/RemoteCall/factory/api/show.ts @@ -15,7 +15,7 @@ import { storageUtils } from "../../utils/storageUtils"; import { reply } from "../../utils/ReplyUtils"; import { configUtils } from "../../utils/configUtils"; -import { session } from "../../utils/sessionUtils"; +import { sessionUtils } from "../../utils/sessionUtils"; import { ApiBase } from "../baseApi"; import { chain } from "../../actionChain/chain"; @@ -196,7 +196,7 @@ class ShowApi extends ApiBase { call(argv) { let that = this; - session.argv = argv; + sessionUtils.argv = argv; if (argv.keyword.length > 0) { // show specific one chain diff --git a/src/RemoteCall/factory/api/star.ts b/src/RemoteCall/factory/api/star.ts index 5f3fea2..e1514b8 100644 --- a/src/RemoteCall/factory/api/star.ts +++ b/src/RemoteCall/factory/api/star.ts @@ -9,7 +9,7 @@ import { reply } from "../../utils/ReplyUtils"; -import { session } from "../../utils/sessionUtils"; +import { sessionUtils } from "../../utils/sessionUtils"; import { ApiBase } from "../baseApi"; import { chain } from "../../actionChain/chain"; @@ -38,7 +38,7 @@ class StarApi extends ApiBase { } call(argv) { - session.argv = argv; + sessionUtils.argv = argv; // translation doesn't affect question lookup chain.getChainHead().getProblem(argv.keyword, true, function (e, problem) { if (e) return reply.info(e); diff --git a/src/RemoteCall/factory/api/submission.ts b/src/RemoteCall/factory/api/submission.ts index a338d17..6c9754b 100644 --- a/src/RemoteCall/factory/api/submission.ts +++ b/src/RemoteCall/factory/api/submission.ts @@ -17,7 +17,7 @@ // import { log } from "../log"; // import { Queue } from "../queue"; // import { corePlugin } from "../core"; -// import { session } from "../session"; +// import { sessionUtils } from "../session"; class SubMission { constructor() {} diff --git a/src/RemoteCall/factory/api/submit.ts b/src/RemoteCall/factory/api/submit.ts index 119080c..01d9364 100644 --- a/src/RemoteCall/factory/api/submit.ts +++ b/src/RemoteCall/factory/api/submit.ts @@ -13,7 +13,7 @@ let lodash = require("lodash"); import { storageUtils } from "../../utils/storageUtils"; import { reply } from "../../utils/ReplyUtils"; -import { session } from "../../utils/sessionUtils"; +import { sessionUtils } from "../../utils/sessionUtils"; import { ApiBase } from "../baseApi"; import { chain } from "../../actionChain/chain"; @@ -58,7 +58,7 @@ class SubmitApi extends ApiBase { } call(argv) { - session.argv = argv; + sessionUtils.argv = argv; if (!storageUtils.exist(argv.filename)) return reply.fatal("File " + argv.filename + " not exist!"); @@ -96,8 +96,8 @@ class SubmitApi extends ApiBase { ); if (result.ok) { - session.updateStat("ac", 1); - session.updateStat("ac.set", problem.fid); + sessionUtils.updateStat("ac", 1); + sessionUtils.updateStat("ac.set", problem.fid); log_obj.system_message.accepted = true; (function () { diff --git a/src/RemoteCall/factory/api/test.ts b/src/RemoteCall/factory/api/test.ts index 2cff296..c8d7134 100644 --- a/src/RemoteCall/factory/api/test.ts +++ b/src/RemoteCall/factory/api/test.ts @@ -13,7 +13,7 @@ let lodash = require("lodash"); import { storageUtils } from "../../utils/storageUtils"; import { reply } from "../../utils/ReplyUtils"; -import { session } from "../../utils/sessionUtils"; +import { sessionUtils } from "../../utils/sessionUtils"; import { ApiBase } from "../baseApi"; import { commUtils } from "../../utils/commUtils"; import { chain } from "../../actionChain/chain"; @@ -234,7 +234,7 @@ class TestApi extends ApiBase { call(argv) { let that = this; - session.argv = argv; + sessionUtils.argv = argv; if (!argv.i) return that.runTest(argv); commUtils.readStdin(function (e, data) { diff --git a/src/RemoteCall/factory/api/user.ts b/src/RemoteCall/factory/api/user.ts index 76be8f9..7dbd4be 100644 --- a/src/RemoteCall/factory/api/user.ts +++ b/src/RemoteCall/factory/api/user.ts @@ -11,7 +11,7 @@ let prompt_out = require("prompt"); import { reply } from "../../utils/ReplyUtils"; -import { session } from "../../utils/sessionUtils"; +import { sessionUtils } from "../../utils/sessionUtils"; import { ApiBase } from "../baseApi"; import { chain } from "../../actionChain/chain"; @@ -60,7 +60,7 @@ class UserApi extends ApiBase { } call(argv) { - session.argv = argv; + sessionUtils.argv = argv; let user: any = null; if (argv.login) { // login @@ -145,7 +145,7 @@ class UserApi extends ApiBase { ); } else { // show current user - user = session.getUser(); + user = sessionUtils.getUser(); if (user) { reply.info(JSON.stringify({ code: 100, user_name: user.name })); } else diff --git a/src/RemoteCall/utils/sessionUtils.ts b/src/RemoteCall/utils/sessionUtils.ts index 87ddf66..521468e 100644 --- a/src/RemoteCall/utils/sessionUtils.ts +++ b/src/RemoteCall/utils/sessionUtils.ts @@ -65,4 +65,4 @@ class Session { storageUtils.setCache(commUtils.KEYS.stat, stats); }; } -export const session: Session = new Session(); +export const sessionUtils: Session = new Session(); From 4a0e44824e2239011f069e5ec84351bdebd72037 Mon Sep 17 00:00:00 2001 From: ccagml Date: Thu, 17 Nov 2022 14:07:16 +0800 Subject: [PATCH 13/26] chainManager --- src/RemoteCall/actionChain/chainManager.ts | 97 ++++++++++++++++ src/RemoteCall/actionChain/chainNode/cache.ts | 4 +- src/RemoteCall/actionChain/chainNode/core.ts | 4 +- .../actionChain/chainNode/leetcode.cn.ts | 4 +- .../actionChain/chainNode/leetcode.ts | 4 +- src/RemoteCall/actionChain/chainNode/retry.ts | 4 +- .../actionChain/chainNode/solution.discuss.ts | 4 +- .../{chain.ts => chainNodeBase.ts} | 104 +----------------- src/RemoteCall/childMain.ts | 17 ++- src/RemoteCall/factory/api/list.ts | 4 +- src/RemoteCall/factory/api/plugin.ts | 8 +- src/RemoteCall/factory/api/query.ts | 10 +- src/RemoteCall/factory/api/show.ts | 6 +- src/RemoteCall/factory/api/star.ts | 36 +++--- src/RemoteCall/factory/api/submit.ts | 8 +- src/RemoteCall/factory/api/test.ts | 6 +- src/RemoteCall/factory/api/user.ts | 16 +-- src/RemoteCall/utils/storageUtils.ts | 1 + 18 files changed, 172 insertions(+), 165 deletions(-) create mode 100644 src/RemoteCall/actionChain/chainManager.ts rename src/RemoteCall/actionChain/{chain.ts => chainNodeBase.ts} (52%) diff --git a/src/RemoteCall/actionChain/chainManager.ts b/src/RemoteCall/actionChain/chainManager.ts new file mode 100644 index 0000000..de91f31 --- /dev/null +++ b/src/RemoteCall/actionChain/chainManager.ts @@ -0,0 +1,97 @@ +/* + * Filename: /home/cc/vscode-leetcode-problem-rating/src/RemoteCall/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 { configUtils } from "../utils/configUtils"; +import { storageUtils } from "../utils/storageUtils"; +import { commUtils } from "../utils/commUtils"; +import { ChainNodeBase } from "./chainNodeBase"; + +export class ChainManager { + id; + name; + ver; + desc; + enabled; + deleted; + builtin; + deps; + next; + plugins: Array = []; + installed: Array = []; + head; // 插件头 是core + config; + constructor() {} + + 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 init(): void { + this.config = configUtils.plugins[this.name] || {}; + } + + public getChainHead(): ChainNodeBase { + return this.head; + } + + public base_init(head: ChainNodeBase): Object { + 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; + 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/RemoteCall/actionChain/chainNode/cache.ts b/src/RemoteCall/actionChain/chainNode/cache.ts index 92517de..9dbd7cb 100644 --- a/src/RemoteCall/actionChain/chainNode/cache.ts +++ b/src/RemoteCall/actionChain/chainNode/cache.ts @@ -7,7 +7,7 @@ * Copyright (c) 2022 ccagml . All rights reserved. */ -import { Chain } from "../chain"; +import { ChainNodeBase } from "../chainNodeBase"; let underscore = require("underscore"); @@ -15,7 +15,7 @@ import { storageUtils } from "../../utils/storageUtils"; import { commUtils } from "../../utils/commUtils"; import { sessionUtils } from "../../utils/sessionUtils"; -class CachePlugin extends Chain { +class CachePlugin extends ChainNodeBase { id = 50; name = "cache"; builtin = true; diff --git a/src/RemoteCall/actionChain/chainNode/core.ts b/src/RemoteCall/actionChain/chainNode/core.ts index b82dcb8..f9fd3e4 100644 --- a/src/RemoteCall/actionChain/chainNode/core.ts +++ b/src/RemoteCall/actionChain/chainNode/core.ts @@ -15,13 +15,13 @@ let cheerio = require("cheerio"); import { storageUtils } from "../../utils/storageUtils"; import { configUtils } from "../../utils/configUtils"; -import { Chain } from "../chain"; +import { ChainNodeBase } from "../chainNodeBase"; function hasTag(o, tag) { return Array.isArray(o) && o.some((x) => x.indexOf(tag.toLowerCase()) >= 0); } -class CorePlugin extends Chain { +class CorePlugin extends ChainNodeBase { id = 99999999; name = "core"; builtin = true; diff --git a/src/RemoteCall/actionChain/chainNode/leetcode.cn.ts b/src/RemoteCall/actionChain/chainNode/leetcode.cn.ts index 7a9d065..a8df828 100644 --- a/src/RemoteCall/actionChain/chainNode/leetcode.cn.ts +++ b/src/RemoteCall/actionChain/chainNode/leetcode.cn.ts @@ -7,7 +7,7 @@ * Copyright (c) 2022 ccagml . All rights reserved. */ -import { Chain } from "./../chain"; +import { ChainNodeBase } from "../chainNodeBase"; let request = require("request"); @@ -15,7 +15,7 @@ import { configUtils } from "../../utils/configUtils"; import { sessionUtils } from "../../utils/sessionUtils"; -class LeetCodeCn extends Chain { +class LeetCodeCn extends ChainNodeBase { id = 15; name = "leetcode.cn"; builtin = true; diff --git a/src/RemoteCall/actionChain/chainNode/leetcode.ts b/src/RemoteCall/actionChain/chainNode/leetcode.ts index e4cd270..50e09cf 100644 --- a/src/RemoteCall/actionChain/chainNode/leetcode.ts +++ b/src/RemoteCall/actionChain/chainNode/leetcode.ts @@ -18,10 +18,10 @@ import { commUtils } from "../../utils/commUtils"; import { storageUtils } from "../../utils/storageUtils"; import { reply } from "../../utils/ReplyUtils"; import { sessionUtils } from "../../utils/sessionUtils"; -import { Chain } from "./../chain"; +import { ChainNodeBase } from "../chainNodeBase"; import { Queue } from "../../utils/queueUtils"; -class LeetCode extends Chain { +class LeetCode extends ChainNodeBase { id = 10; name = "leetcode"; builtin = true; diff --git a/src/RemoteCall/actionChain/chainNode/retry.ts b/src/RemoteCall/actionChain/chainNode/retry.ts index 02c9549..4349c8a 100644 --- a/src/RemoteCall/actionChain/chainNode/retry.ts +++ b/src/RemoteCall/actionChain/chainNode/retry.ts @@ -7,11 +7,11 @@ * Copyright (c) 2022 ccagml . All rights reserved. */ -import { Chain } from "./../chain"; +import { ChainNodeBase } from "../chainNodeBase"; import { configUtils } from "../../utils/configUtils"; import { sessionUtils } from "../../utils/sessionUtils"; -class RetryPlugin extends Chain { +class RetryPlugin extends ChainNodeBase { id = 30; name = "retry"; builtin = true; diff --git a/src/RemoteCall/actionChain/chainNode/solution.discuss.ts b/src/RemoteCall/actionChain/chainNode/solution.discuss.ts index 3bc8225..781397b 100644 --- a/src/RemoteCall/actionChain/chainNode/solution.discuss.ts +++ b/src/RemoteCall/actionChain/chainNode/solution.discuss.ts @@ -11,9 +11,9 @@ let request = require("request"); import { reply } from "../../utils/ReplyUtils"; import { sessionUtils } from "../../utils/sessionUtils"; -import { Chain } from "./../chain"; +import { ChainNodeBase } from "../chainNodeBase"; -class SolutionDiscuss extends Chain { +class SolutionDiscuss extends ChainNodeBase { id = 200; name = "solution.discuss"; builtin = true; diff --git a/src/RemoteCall/actionChain/chain.ts b/src/RemoteCall/actionChain/chainNodeBase.ts similarity index 52% rename from src/RemoteCall/actionChain/chain.ts rename to src/RemoteCall/actionChain/chainNodeBase.ts index 3ef2f70..aa702d3 100644 --- a/src/RemoteCall/actionChain/chain.ts +++ b/src/RemoteCall/actionChain/chainNodeBase.ts @@ -1,102 +1,12 @@ -/* - * Filename: /home/cc/vscode-leetcode-problem-rating/src/RemoteCall/actionChain/chain.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 { configUtils } from "../utils/configUtils"; -import { storageUtils } from "../utils/storageUtils"; -import { commUtils } from "../utils/commUtils"; - -export class Chain { - id; - name; - ver; - desc; - enabled; - deleted; - builtin; - deps; - next; - plugins: Array = []; - installed: Array = []; - head; // 插件头 是core - config; - constructor() {} - - 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 init(): void { - this.config = configUtils.plugins[this.name] || {}; - this.next = null; - } - - public getChainHead(): Chain { - return this.head; - } - - public base_init(head: Chain): Object { - this.head = head; - const stats = storageUtils.getCache(commUtils.KEYS.plugins) || {}; - let file_plugin: Array = storageUtils.listCodeDir( - "../actionChain/chainNode" - ); - 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: Chain): void { +export class ChainNodeBase { + public init() {} + next: ChainNodeBase; + enabled: boolean; + builtin: boolean = true; + public setNext(next: ChainNodeBase): void { Object.setPrototypeOf(this, next); this.next = next; } - public save_all(): void { - for (let p of this.plugins) { - p.save(); - } - } - public getProblems(Translate: boolean, cb: Function): void { this.next.getProblems(Translate, cb); } @@ -189,5 +99,3 @@ export class Chain { this.next.getRating(cb); } } - -export const chain: Chain = new Chain(); diff --git a/src/RemoteCall/childMain.ts b/src/RemoteCall/childMain.ts index 283d2fc..141ed2b 100644 --- a/src/RemoteCall/childMain.ts +++ b/src/RemoteCall/childMain.ts @@ -7,7 +7,7 @@ * Copyright (c) 2022 ccagml . All rights reserved. */ -import { chain } from "./actionChain/chain"; +import { chainMgr } from "./actionChain/chainManager"; import { corePlugin } from "./actionChain/chainNode/core"; import { configUtils } from "./utils/configUtils"; import { reply } from "./utils/ReplyUtils"; @@ -26,15 +26,12 @@ class Main { configUtils.init(JSON.parse(process.env.ccagml || "{}")); reply.init(); storageUtils.init(); - if (chain.base_init(corePlugin)) { - chain.save(); - storageUtils.initCache(); - let com_str = process.argv[2]; - let curApi: IApi | undefined = apiFactory.getApi(com_str); - if (curApi != undefined) { - curApi.call(curApi.callArg(process.argv)); - } - } + + chainMgr.base_init(corePlugin); + chainMgr.save(); + let com_str: string = process.argv[2]; + let curApi: IApi | undefined = apiFactory.getApi(com_str); + curApi?.call(curApi?.callArg(process.argv)); } } diff --git a/src/RemoteCall/factory/api/list.ts b/src/RemoteCall/factory/api/list.ts index 308f1b8..ab097df 100644 --- a/src/RemoteCall/factory/api/list.ts +++ b/src/RemoteCall/factory/api/list.ts @@ -10,7 +10,7 @@ import { reply } from "../../utils/ReplyUtils"; import { sessionUtils } from "../../utils/sessionUtils"; import { ApiBase } from "../baseApi"; -import { chain } from "../../actionChain/chain"; +import { chainMgr } from "../../actionChain/chainManager"; class ListApi extends ApiBase { constructor() { @@ -71,7 +71,7 @@ class ListApi extends ApiBase { call(argv) { sessionUtils.argv = argv; - chain.getChainHead().filterProblems(argv, function (e, problems) { + chainMgr.getChainHead().filterProblems(argv, function (e, problems) { if (e) return reply.info(e); let new_objcet: Array = []; problems.forEach((element) => { diff --git a/src/RemoteCall/factory/api/plugin.ts b/src/RemoteCall/factory/api/plugin.ts index 673c325..cfd1ff0 100644 --- a/src/RemoteCall/factory/api/plugin.ts +++ b/src/RemoteCall/factory/api/plugin.ts @@ -9,7 +9,7 @@ import { configUtils } from "../../utils/configUtils"; import { reply } from "../../utils/ReplyUtils"; -import { chain } from "../../actionChain/chain"; +import { chainMgr } from "../../actionChain/chainManager"; import { sessionUtils } from "../../utils/sessionUtils"; import { ApiBase } from "../baseApi"; @@ -52,7 +52,7 @@ class PluginApi extends ApiBase { call(argv) { sessionUtils.argv = argv; - let all_plugin = chain.installed; + let all_plugin = chainMgr.installed; const name = argv.name; // if (argv.install) { @@ -60,7 +60,7 @@ class PluginApi extends ApiBase { // if (e) return log.fatal(e); // p.help(); // p.save(); - // chain.init(); + // chainMgr.init(); // }; // return; @@ -83,7 +83,7 @@ class PluginApi extends ApiBase { } else if (argv.delete) { // p.delete(); p.save(); - chain.init(); + chainMgr.init(); } else if (argv.config) { reply.info(JSON.stringify(configUtils.plugins[name] || {}, null, 2)); } diff --git a/src/RemoteCall/factory/api/query.ts b/src/RemoteCall/factory/api/query.ts index ed4cffb..09e3638 100644 --- a/src/RemoteCall/factory/api/query.ts +++ b/src/RemoteCall/factory/api/query.ts @@ -11,7 +11,7 @@ import { reply } from "../../utils/ReplyUtils"; import { sessionUtils } from "../../utils/sessionUtils"; import { ApiBase } from "../baseApi"; -import { chain } from "../../actionChain/chain"; +import { chainMgr } from "../../actionChain/chainManager"; class QueryApi extends ApiBase { constructor() { @@ -56,17 +56,17 @@ class QueryApi extends ApiBase { call(argv) { sessionUtils.argv = argv; if (argv.a) { - chain.getChainHead().getTodayQuestion(function (e, result) { + chainMgr.getChainHead().getTodayQuestion(function (e, result) { if (e) return; reply.info(JSON.stringify(result)); }); } else if (argv.b) { - chain.getChainHead().getUserContest(argv.b, function (e, result) { + chainMgr.getChainHead().getUserContest(argv.b, function (e, result) { if (e) return; reply.info(JSON.stringify(result)); }); } else if (argv.c) { - chain.getChainHead().getRating(function (e, result) { + chainMgr.getChainHead().getRating(function (e, result) { if (e) { let log_data = { code: 101, @@ -82,7 +82,7 @@ class QueryApi extends ApiBase { reply.info(JSON.stringify(log_data)); }); } else if (argv.z) { - chain.getChainHead().getQueryZ(argv.z, function (e, result) { + chainMgr.getChainHead().getQueryZ(argv.z, function (e, result) { if (e) return; reply.info(JSON.stringify(result)); }); diff --git a/src/RemoteCall/factory/api/show.ts b/src/RemoteCall/factory/api/show.ts index 151f94c..959d701 100644 --- a/src/RemoteCall/factory/api/show.ts +++ b/src/RemoteCall/factory/api/show.ts @@ -17,7 +17,7 @@ import { configUtils } from "../../utils/configUtils"; import { sessionUtils } from "../../utils/sessionUtils"; import { ApiBase } from "../baseApi"; -import { chain } from "../../actionChain/chain"; +import { chainMgr } from "../../actionChain/chainManager"; class ShowApi extends ApiBase { constructor() { @@ -142,7 +142,7 @@ class ShowApi extends ApiBase { code: template.defaultCode, tpl: argv.extra ? "detailed" : "codeonly", }; - code = chain.getChainHead().exportProblem(problem, opts); + code = chainMgr.getChainHead().exportProblem(problem, opts); } let filename; @@ -199,7 +199,7 @@ class ShowApi extends ApiBase { sessionUtils.argv = argv; if (argv.keyword.length > 0) { // show specific one - chain + chainMgr .getChainHead() .getProblem(argv.keyword, !argv.dontTranslate, function (e, problem) { if (e) return reply.info(e); diff --git a/src/RemoteCall/factory/api/star.ts b/src/RemoteCall/factory/api/star.ts index e1514b8..bb68638 100644 --- a/src/RemoteCall/factory/api/star.ts +++ b/src/RemoteCall/factory/api/star.ts @@ -11,7 +11,7 @@ import { reply } from "../../utils/ReplyUtils"; import { sessionUtils } from "../../utils/sessionUtils"; import { ApiBase } from "../baseApi"; -import { chain } from "../../actionChain/chain"; +import { chainMgr } from "../../actionChain/chainManager"; class StarApi extends ApiBase { constructor() { @@ -40,21 +40,25 @@ class StarApi extends ApiBase { call(argv) { sessionUtils.argv = argv; // translation doesn't affect question lookup - chain.getChainHead().getProblem(argv.keyword, true, function (e, problem) { - if (e) return reply.info(e); - - chain - .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" - }` - ); - chain.getChainHead().updateProblem(problem, { starred: starred }); - }); - }); + 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 }); + }); + }); } } diff --git a/src/RemoteCall/factory/api/submit.ts b/src/RemoteCall/factory/api/submit.ts index 01d9364..3fb8c81 100644 --- a/src/RemoteCall/factory/api/submit.ts +++ b/src/RemoteCall/factory/api/submit.ts @@ -15,7 +15,7 @@ import { reply } from "../../utils/ReplyUtils"; import { sessionUtils } from "../../utils/sessionUtils"; import { ApiBase } from "../baseApi"; -import { chain } from "../../actionChain/chain"; +import { chainMgr } from "../../actionChain/chainManager"; class SubmitApi extends ApiBase { constructor() { @@ -65,13 +65,13 @@ class SubmitApi extends ApiBase { const meta = storageUtils.meta(argv.filename); let that = this; // translation doesn't affect problem lookup - chain.getChainHead().getProblem(meta, true, function (e, problem) { + chainMgr.getChainHead().getProblem(meta, true, function (e, problem) { if (e) return reply.info(e); problem.file = argv.filename; problem.lang = meta.lang; - chain.getChainHead().submitProblem(problem, function (e, results) { + chainMgr.getChainHead().submitProblem(problem, function (e, results) { if (e) return reply.info(e); const result = results[0]; @@ -130,7 +130,7 @@ class SubmitApi extends ApiBase { that.printResult(result, "stdout", log_obj); } reply.info(JSON.stringify(log_obj)); - chain.getChainHead().updateProblem(problem, { + chainMgr.getChainHead().updateProblem(problem, { state: result.ok ? "ac" : "notac", }); }); diff --git a/src/RemoteCall/factory/api/test.ts b/src/RemoteCall/factory/api/test.ts index c8d7134..ceffa74 100644 --- a/src/RemoteCall/factory/api/test.ts +++ b/src/RemoteCall/factory/api/test.ts @@ -16,7 +16,7 @@ import { reply } from "../../utils/ReplyUtils"; import { sessionUtils } from "../../utils/sessionUtils"; import { ApiBase } from "../baseApi"; import { commUtils } from "../../utils/commUtils"; -import { chain } from "../../actionChain/chain"; +import { chainMgr } from "../../actionChain/chainManager"; class TestApi extends ApiBase { constructor() { @@ -88,7 +88,7 @@ class TestApi extends ApiBase { // [key: string]: string[]; // messages: string[]; - chain.getChainHead().getProblem(meta, true, function (e, problem) { + chainMgr.getChainHead().getProblem(meta, true, function (e, problem) { if (e) return reply.info( JSON.stringify({ @@ -193,7 +193,7 @@ class TestApi extends ApiBase { problem.file = argv.filename; problem.lang = meta.lang; - chain.getChainHead().testProblem(problem, function (e, results) { + chainMgr.getChainHead().testProblem(problem, function (e, results) { if (e) return reply.info(JSON.stringify(e)); results = _.sortBy(results, (x) => x.type); diff --git a/src/RemoteCall/factory/api/user.ts b/src/RemoteCall/factory/api/user.ts index 7dbd4be..e1ccdc4 100644 --- a/src/RemoteCall/factory/api/user.ts +++ b/src/RemoteCall/factory/api/user.ts @@ -14,7 +14,7 @@ import { reply } from "../../utils/ReplyUtils"; import { sessionUtils } from "../../utils/sessionUtils"; import { ApiBase } from "../baseApi"; -import { chain } from "../../actionChain/chain"; +import { chainMgr } from "../../actionChain/chainManager"; class UserApi extends ApiBase { constructor() { @@ -77,7 +77,7 @@ class UserApi extends ApiBase { return reply.info(JSON.stringify({ code: -1, msg: e.msg || e })); } - chain.getChainHead().login(user, function (e, user) { + chainMgr.getChainHead().login(user, function (e, user) { if (e) { return reply.info(JSON.stringify({ code: -2, msg: e.msg || e })); } @@ -87,7 +87,7 @@ class UserApi extends ApiBase { ); } else if (argv.logout) { // logout - user = chain.getChainHead().logout(user, true); + 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?" })); @@ -95,10 +95,10 @@ class UserApi extends ApiBase { } else if (argv.github || argv.linkedin) { // add future third parties here const functionMap = new Map([ - ["g", chain.getChainHead().githubLogin], - ["github", chain.getChainHead().githubLogin], - ["i", chain.getChainHead().linkedinLogin], - ["linkedin", chain.getChainHead().linkedinLogin], + ["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); @@ -136,7 +136,7 @@ class UserApi extends ApiBase { ], function (e, user) { if (e) return reply.info(e); - chain.getChainHead().cookieLogin(user, function (e, user) { + 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 })); diff --git a/src/RemoteCall/utils/storageUtils.ts b/src/RemoteCall/utils/storageUtils.ts index aa0550d..47b95b6 100644 --- a/src/RemoteCall/utils/storageUtils.ts +++ b/src/RemoteCall/utils/storageUtils.ts @@ -166,6 +166,7 @@ class StorageUtils { interpolate: /\$\{(.+?)\}/g, }; this.mkdir(this.homeDir()); + this.initCache(); } public isWindows() { From 59d507a533b366d88034cd039642b767c80ee09b Mon Sep 17 00:00:00 2001 From: ccagml Date: Thu, 17 Nov 2022 15:51:41 +0800 Subject: [PATCH 14/26] update --- src/RemoteCall/actionChain/chainManager.ts | 41 +++++++-------------- src/RemoteCall/actionChain/chainNodeBase.ts | 20 +++++++++- src/RemoteCall/childMain.ts | 3 +- src/RemoteCall/factory/api/plugin.ts | 13 +------ 4 files changed, 34 insertions(+), 43 deletions(-) diff --git a/src/RemoteCall/actionChain/chainManager.ts b/src/RemoteCall/actionChain/chainManager.ts index de91f31..dd316ba 100644 --- a/src/RemoteCall/actionChain/chainManager.ts +++ b/src/RemoteCall/actionChain/chainManager.ts @@ -9,7 +9,6 @@ let underscore = require("underscore"); -import { configUtils } from "../utils/configUtils"; import { storageUtils } from "../utils/storageUtils"; import { commUtils } from "../utils/commUtils"; import { ChainNodeBase } from "./chainNodeBase"; @@ -19,36 +18,21 @@ export class ChainManager { name; ver; desc; - enabled; - deleted; - builtin; - deps; - next; - plugins: Array = []; - installed: Array = []; - head; // 插件头 是core - config; - constructor() {} - - 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); - } + plugins: Array = []; + installed: Array = []; + head: ChainNodeBase; // 插件头 是core - public init(): void { - this.config = configUtils.plugins[this.name] || {}; - } + constructor() {} public getChainHead(): ChainNodeBase { return this.head; } - public base_init(head: ChainNodeBase): Object { - this.head = 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" @@ -80,10 +64,13 @@ export class ChainManager { // 连成链表状 this.plugins = this.installed.filter((x) => x.enabled); let last = head; - for (let p of this.plugins) { - last.setNext(p); - last = p; + if (last) { + for (let p of this.plugins) { + last.setNext(p); + last = p; + } } + return true; } diff --git a/src/RemoteCall/actionChain/chainNodeBase.ts b/src/RemoteCall/actionChain/chainNodeBase.ts index aa702d3..3147fdb 100644 --- a/src/RemoteCall/actionChain/chainNodeBase.ts +++ b/src/RemoteCall/actionChain/chainNodeBase.ts @@ -1,8 +1,24 @@ +import { commUtils } from "../utils/commUtils"; +import { storageUtils } from "../utils/storageUtils"; + export class ChainNodeBase { - public init() {} - next: 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; diff --git a/src/RemoteCall/childMain.ts b/src/RemoteCall/childMain.ts index 141ed2b..1ce2999 100644 --- a/src/RemoteCall/childMain.ts +++ b/src/RemoteCall/childMain.ts @@ -26,9 +26,8 @@ class Main { configUtils.init(JSON.parse(process.env.ccagml || "{}")); reply.init(); storageUtils.init(); + chainMgr.init(corePlugin); - chainMgr.base_init(corePlugin); - chainMgr.save(); let com_str: string = process.argv[2]; let curApi: IApi | undefined = apiFactory.getApi(com_str); curApi?.call(curApi?.callArg(process.argv)); diff --git a/src/RemoteCall/factory/api/plugin.ts b/src/RemoteCall/factory/api/plugin.ts index cfd1ff0..53823c2 100644 --- a/src/RemoteCall/factory/api/plugin.ts +++ b/src/RemoteCall/factory/api/plugin.ts @@ -55,17 +55,6 @@ class PluginApi extends ApiBase { let all_plugin = chainMgr.installed; const name = argv.name; - // if (argv.install) { - // const cb = function (e, p) { - // if (e) return log.fatal(e); - // p.help(); - // p.save(); - // chainMgr.init(); - // }; - - // return; - // } - if (name) { all_plugin = all_plugin.filter((x) => x.name === name); } @@ -83,7 +72,7 @@ class PluginApi extends ApiBase { } else if (argv.delete) { // p.delete(); p.save(); - chainMgr.init(); + chainMgr.init(undefined); } else if (argv.config) { reply.info(JSON.stringify(configUtils.plugins[name] || {}, null, 2)); } From 77396dc1079b49775f8f23ed3581b98fdc868b18 Mon Sep 17 00:00:00 2001 From: ccagml Date: Thu, 17 Nov 2022 15:55:37 +0800 Subject: [PATCH 15/26] update --- src/RemoteCall/utils/ReplyUtils.ts | 8 ++++---- src/RemoteCall/utils/commUtils.ts | 6 +++--- src/RemoteCall/utils/configUtils.ts | 20 ++++++++++---------- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/RemoteCall/utils/ReplyUtils.ts b/src/RemoteCall/utils/ReplyUtils.ts index 3dd7f3f..b3a0332 100644 --- a/src/RemoteCall/utils/ReplyUtils.ts +++ b/src/RemoteCall/utils/ReplyUtils.ts @@ -11,17 +11,17 @@ let _ = require("underscore"); class Reply { output = _.bind(console.log, console); - level; + level: any; levels = new Map([ ["INFO", { value: 2 }], ["WARN", { value: 3 }], ["ERROR", { value: 4 }], ]); - setLevel(name) { + setLevel(name: any) { this.level = this.levels.get(name) || this.levels.get("INFO"); } - fail(e) { + fail(e: any) { let msg = e.msg || e; if (e.statusCode) { msg += " [code=" + e.statusCode + "]"; @@ -29,7 +29,7 @@ class Reply { this.error(msg); } - fatal(e) { + fatal(e: any) { this.error(e); process.exit(1); } diff --git a/src/RemoteCall/utils/commUtils.ts b/src/RemoteCall/utils/commUtils.ts index 25724a3..f25fb7c 100644 --- a/src/RemoteCall/utils/commUtils.ts +++ b/src/RemoteCall/utils/commUtils.ts @@ -23,7 +23,7 @@ class CommUtils { }; } - getNameByLevel(level) { + getNameByLevel(level: any) { switch (level) { case 1: return "Easy"; @@ -62,7 +62,7 @@ class CommUtils { stdin.on("error", cb); } - getSetCookieValue(resp, key) { + getSetCookieValue(resp: any, key: any) { const cookies = resp.headers["set-cookie"]; if (!cookies) return null; @@ -76,7 +76,7 @@ class CommUtils { return null; } - printSafeHTTP(msg) { + printSafeHTTP(msg: any) { return msg .replace(/(Cookie\s*:\s*)'.*?'/, "$1") .replace(/('X-CSRFToken'\s*:\s*)'.*?'/, "$1") diff --git a/src/RemoteCall/utils/configUtils.ts b/src/RemoteCall/utils/configUtils.ts index b8d2a37..d133cf7 100644 --- a/src/RemoteCall/utils/configUtils.ts +++ b/src/RemoteCall/utils/configUtils.ts @@ -10,16 +10,16 @@ let underscore = require("underscore"); class Config { - LCPTCTX; - app; - sys; - autologin; - code; - file; - color; - icon; - network; - plugins; + 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"], From 8341ae578ba4cac98102f612c210d32fd6d764c7 Mon Sep 17 00:00:00 2001 From: ccagml Date: Thu, 17 Nov 2022 16:02:12 +0800 Subject: [PATCH 16/26] =?UTF-8?q?=E6=96=87=E4=BB=B6=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/RemoteCall/childMain.ts | 2 +- src/RemoteCall/factory/api/cache.ts | 2 +- src/RemoteCall/factory/api/list.ts | 2 +- src/RemoteCall/factory/api/plugin.ts | 2 +- src/RemoteCall/factory/api/query.ts | 2 +- src/RemoteCall/factory/api/show.ts | 2 +- src/RemoteCall/factory/api/star.ts | 2 +- src/RemoteCall/factory/api/submit.ts | 2 +- src/RemoteCall/factory/api/test.ts | 2 +- src/RemoteCall/factory/api/user.ts | 2 +- src/RemoteCall/factory/{baseApi.ts => apiBase.ts} | 9 +++++++++ src/RemoteCall/factory/apiFactory.ts | 2 +- 12 files changed, 20 insertions(+), 11 deletions(-) rename src/RemoteCall/factory/{baseApi.ts => apiBase.ts} (89%) diff --git a/src/RemoteCall/childMain.ts b/src/RemoteCall/childMain.ts index 1ce2999..3991caf 100644 --- a/src/RemoteCall/childMain.ts +++ b/src/RemoteCall/childMain.ts @@ -13,7 +13,7 @@ import { configUtils } from "./utils/configUtils"; import { reply } from "./utils/ReplyUtils"; import { storageUtils } from "./utils/storageUtils"; import { apiFactory } from "./factory/apiFactory"; -import { IApi } from "./factory/baseApi"; +import { IApi } from "./factory/apiBase"; class Main { constructor() { diff --git a/src/RemoteCall/factory/api/cache.ts b/src/RemoteCall/factory/api/cache.ts index 0292c85..467efcb 100644 --- a/src/RemoteCall/factory/api/cache.ts +++ b/src/RemoteCall/factory/api/cache.ts @@ -9,7 +9,7 @@ import { storageUtils } from "../../utils/storageUtils"; import { sessionUtils } from "../../utils/sessionUtils"; -import { ApiBase } from "../baseApi"; +import { ApiBase } from "../apiBase"; class CacheApi extends ApiBase { constructor() { diff --git a/src/RemoteCall/factory/api/list.ts b/src/RemoteCall/factory/api/list.ts index ab097df..931b366 100644 --- a/src/RemoteCall/factory/api/list.ts +++ b/src/RemoteCall/factory/api/list.ts @@ -9,7 +9,7 @@ import { reply } from "../../utils/ReplyUtils"; import { sessionUtils } from "../../utils/sessionUtils"; -import { ApiBase } from "../baseApi"; +import { ApiBase } from "../apiBase"; import { chainMgr } from "../../actionChain/chainManager"; class ListApi extends ApiBase { diff --git a/src/RemoteCall/factory/api/plugin.ts b/src/RemoteCall/factory/api/plugin.ts index 53823c2..7bf6da6 100644 --- a/src/RemoteCall/factory/api/plugin.ts +++ b/src/RemoteCall/factory/api/plugin.ts @@ -11,7 +11,7 @@ import { configUtils } from "../../utils/configUtils"; import { reply } from "../../utils/ReplyUtils"; import { chainMgr } from "../../actionChain/chainManager"; import { sessionUtils } from "../../utils/sessionUtils"; -import { ApiBase } from "../baseApi"; +import { ApiBase } from "../apiBase"; class PluginApi extends ApiBase { constructor() { diff --git a/src/RemoteCall/factory/api/query.ts b/src/RemoteCall/factory/api/query.ts index 09e3638..5bd3f67 100644 --- a/src/RemoteCall/factory/api/query.ts +++ b/src/RemoteCall/factory/api/query.ts @@ -9,7 +9,7 @@ import { reply } from "../../utils/ReplyUtils"; import { sessionUtils } from "../../utils/sessionUtils"; -import { ApiBase } from "../baseApi"; +import { ApiBase } from "../apiBase"; import { chainMgr } from "../../actionChain/chainManager"; diff --git a/src/RemoteCall/factory/api/show.ts b/src/RemoteCall/factory/api/show.ts index 959d701..dc1b364 100644 --- a/src/RemoteCall/factory/api/show.ts +++ b/src/RemoteCall/factory/api/show.ts @@ -16,7 +16,7 @@ import { reply } from "../../utils/ReplyUtils"; import { configUtils } from "../../utils/configUtils"; import { sessionUtils } from "../../utils/sessionUtils"; -import { ApiBase } from "../baseApi"; +import { ApiBase } from "../apiBase"; import { chainMgr } from "../../actionChain/chainManager"; class ShowApi extends ApiBase { diff --git a/src/RemoteCall/factory/api/star.ts b/src/RemoteCall/factory/api/star.ts index bb68638..a216546 100644 --- a/src/RemoteCall/factory/api/star.ts +++ b/src/RemoteCall/factory/api/star.ts @@ -10,7 +10,7 @@ import { reply } from "../../utils/ReplyUtils"; import { sessionUtils } from "../../utils/sessionUtils"; -import { ApiBase } from "../baseApi"; +import { ApiBase } from "../apiBase"; import { chainMgr } from "../../actionChain/chainManager"; class StarApi extends ApiBase { diff --git a/src/RemoteCall/factory/api/submit.ts b/src/RemoteCall/factory/api/submit.ts index 3fb8c81..4e0bae2 100644 --- a/src/RemoteCall/factory/api/submit.ts +++ b/src/RemoteCall/factory/api/submit.ts @@ -14,7 +14,7 @@ import { storageUtils } from "../../utils/storageUtils"; import { reply } from "../../utils/ReplyUtils"; import { sessionUtils } from "../../utils/sessionUtils"; -import { ApiBase } from "../baseApi"; +import { ApiBase } from "../apiBase"; import { chainMgr } from "../../actionChain/chainManager"; class SubmitApi extends ApiBase { diff --git a/src/RemoteCall/factory/api/test.ts b/src/RemoteCall/factory/api/test.ts index ceffa74..d02ff6a 100644 --- a/src/RemoteCall/factory/api/test.ts +++ b/src/RemoteCall/factory/api/test.ts @@ -14,7 +14,7 @@ import { storageUtils } from "../../utils/storageUtils"; import { reply } from "../../utils/ReplyUtils"; import { sessionUtils } from "../../utils/sessionUtils"; -import { ApiBase } from "../baseApi"; +import { ApiBase } from "../apiBase"; import { commUtils } from "../../utils/commUtils"; import { chainMgr } from "../../actionChain/chainManager"; diff --git a/src/RemoteCall/factory/api/user.ts b/src/RemoteCall/factory/api/user.ts index e1ccdc4..1d6510c 100644 --- a/src/RemoteCall/factory/api/user.ts +++ b/src/RemoteCall/factory/api/user.ts @@ -12,7 +12,7 @@ let prompt_out = require("prompt"); import { reply } from "../../utils/ReplyUtils"; import { sessionUtils } from "../../utils/sessionUtils"; -import { ApiBase } from "../baseApi"; +import { ApiBase } from "../apiBase"; import { chainMgr } from "../../actionChain/chainManager"; diff --git a/src/RemoteCall/factory/baseApi.ts b/src/RemoteCall/factory/apiBase.ts similarity index 89% rename from src/RemoteCall/factory/baseApi.ts rename to src/RemoteCall/factory/apiBase.ts index 4030df7..f36415e 100644 --- a/src/RemoteCall/factory/baseApi.ts +++ b/src/RemoteCall/factory/apiBase.ts @@ -1,3 +1,12 @@ +/* + * Filename: /home/cc/vscode-leetcode-problem-rating/src/RemoteCall/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; diff --git a/src/RemoteCall/factory/apiFactory.ts b/src/RemoteCall/factory/apiFactory.ts index b6bdaef..a952f81 100644 --- a/src/RemoteCall/factory/apiFactory.ts +++ b/src/RemoteCall/factory/apiFactory.ts @@ -7,7 +7,7 @@ import { starApi } from "./api/star"; import { submitApi } from "./api/submit"; import { testApi } from "./api/test"; import { userApi } from "./api/user"; -import { IApi } from "./baseApi"; +import { IApi } from "./apiBase"; class ApiFactory { constructor() {} From 7c3f12113ad47796d54d53aa71d1d1c102daff48 Mon Sep 17 00:00:00 2001 From: ccagml Date: Thu, 17 Nov 2022 16:05:43 +0800 Subject: [PATCH 17/26] update --- .../factory/api/{cache.ts => cacheApi.ts} | 4 ++-- .../factory/api/{list.ts => listApi.ts} | 4 ++-- .../factory/api/{plugin.ts => pluginApi.ts} | 4 ++-- .../factory/api/{query.ts => queryApi.ts} | 4 ++-- .../factory/api/{show.ts => showApi.ts} | 4 ++-- .../factory/api/{star.ts => starApi.ts} | 4 ++-- .../api/{submission.ts => submissionApi.ts} | 0 .../factory/api/{submit.ts => submitApi.ts} | 4 ++-- .../factory/api/{test.ts => testApi.ts} | 4 ++-- .../factory/api/{user.ts => userApi.ts} | 4 ++-- src/RemoteCall/factory/apiFactory.ts | 18 +++++++++--------- 11 files changed, 27 insertions(+), 27 deletions(-) rename src/RemoteCall/factory/api/{cache.ts => cacheApi.ts} (93%) rename src/RemoteCall/factory/api/{list.ts => listApi.ts} (96%) rename src/RemoteCall/factory/api/{plugin.ts => pluginApi.ts} (95%) rename src/RemoteCall/factory/api/{query.ts => queryApi.ts} (96%) rename src/RemoteCall/factory/api/{show.ts => showApi.ts} (98%) rename src/RemoteCall/factory/api/{star.ts => starApi.ts} (94%) rename src/RemoteCall/factory/api/{submission.ts => submissionApi.ts} (100%) rename src/RemoteCall/factory/api/{submit.ts => submitApi.ts} (97%) rename src/RemoteCall/factory/api/{test.ts => testApi.ts} (98%) rename src/RemoteCall/factory/api/{user.ts => userApi.ts} (98%) diff --git a/src/RemoteCall/factory/api/cache.ts b/src/RemoteCall/factory/api/cacheApi.ts similarity index 93% rename from src/RemoteCall/factory/api/cache.ts rename to src/RemoteCall/factory/api/cacheApi.ts index 467efcb..6d1b959 100644 --- a/src/RemoteCall/factory/api/cache.ts +++ b/src/RemoteCall/factory/api/cacheApi.ts @@ -1,7 +1,7 @@ /* - * Filename: /home/cc/vscode-leetcode-problem-rating/src/RemoteCall/factory/api/cache.ts + * Filename: /home/cc/vscode-leetcode-problem-rating/src/RemoteCall/factory/api/cacheApi.ts * Path: /home/cc/vscode-leetcode-problem-rating - * Created Date: Monday, November 14th 2022, 4:04:31 pm + * Created Date: Thursday, November 17th 2022, 11:44:14 am * Author: ccagml * * Copyright (c) 2022 ccagml . All rights reserved. diff --git a/src/RemoteCall/factory/api/list.ts b/src/RemoteCall/factory/api/listApi.ts similarity index 96% rename from src/RemoteCall/factory/api/list.ts rename to src/RemoteCall/factory/api/listApi.ts index 931b366..f3285a7 100644 --- a/src/RemoteCall/factory/api/list.ts +++ b/src/RemoteCall/factory/api/listApi.ts @@ -1,7 +1,7 @@ /* - * Filename: /home/cc/vscode-leetcode-problem-rating/src/RemoteCall/factory/api/list.ts + * Filename: /home/cc/vscode-leetcode-problem-rating/src/RemoteCall/factory/api/listApi.ts * Path: /home/cc/vscode-leetcode-problem-rating - * Created Date: Monday, November 14th 2022, 4:04:31 pm + * Created Date: Thursday, November 17th 2022, 11:44:14 am * Author: ccagml * * Copyright (c) 2022 ccagml . All rights reserved. diff --git a/src/RemoteCall/factory/api/plugin.ts b/src/RemoteCall/factory/api/pluginApi.ts similarity index 95% rename from src/RemoteCall/factory/api/plugin.ts rename to src/RemoteCall/factory/api/pluginApi.ts index 7bf6da6..d9979c3 100644 --- a/src/RemoteCall/factory/api/plugin.ts +++ b/src/RemoteCall/factory/api/pluginApi.ts @@ -1,7 +1,7 @@ /* - * Filename: /home/cc/vscode-leetcode-problem-rating/src/RemoteCall/factory/api/plugin.ts + * Filename: /home/cc/vscode-leetcode-problem-rating/src/RemoteCall/factory/api/pluginApi.ts * Path: /home/cc/vscode-leetcode-problem-rating - * Created Date: Monday, November 14th 2022, 4:04:31 pm + * Created Date: Thursday, November 17th 2022, 11:44:14 am * Author: ccagml * * Copyright (c) 2022 ccagml . All rights reserved. diff --git a/src/RemoteCall/factory/api/query.ts b/src/RemoteCall/factory/api/queryApi.ts similarity index 96% rename from src/RemoteCall/factory/api/query.ts rename to src/RemoteCall/factory/api/queryApi.ts index 5bd3f67..be7de61 100644 --- a/src/RemoteCall/factory/api/query.ts +++ b/src/RemoteCall/factory/api/queryApi.ts @@ -1,7 +1,7 @@ /* - * Filename: /home/cc/vscode-leetcode-problem-rating/src/RemoteCall/factory/api/query.ts + * Filename: /home/cc/vscode-leetcode-problem-rating/src/RemoteCall/factory/api/queryApi.ts * Path: /home/cc/vscode-leetcode-problem-rating - * Created Date: Monday, November 14th 2022, 4:04:31 pm + * Created Date: Thursday, November 17th 2022, 11:44:14 am * Author: ccagml * * Copyright (c) 2022 ccagml . All rights reserved. diff --git a/src/RemoteCall/factory/api/show.ts b/src/RemoteCall/factory/api/showApi.ts similarity index 98% rename from src/RemoteCall/factory/api/show.ts rename to src/RemoteCall/factory/api/showApi.ts index dc1b364..2a6ee5c 100644 --- a/src/RemoteCall/factory/api/show.ts +++ b/src/RemoteCall/factory/api/showApi.ts @@ -1,7 +1,7 @@ /* - * Filename: /home/cc/vscode-leetcode-problem-rating/src/RemoteCall/factory/api/show.ts + * Filename: /home/cc/vscode-leetcode-problem-rating/src/RemoteCall/factory/api/showApi.ts * Path: /home/cc/vscode-leetcode-problem-rating - * Created Date: Monday, November 14th 2022, 4:04:31 pm + * Created Date: Thursday, November 17th 2022, 11:44:14 am * Author: ccagml * * Copyright (c) 2022 ccagml . All rights reserved. diff --git a/src/RemoteCall/factory/api/star.ts b/src/RemoteCall/factory/api/starApi.ts similarity index 94% rename from src/RemoteCall/factory/api/star.ts rename to src/RemoteCall/factory/api/starApi.ts index a216546..dff35db 100644 --- a/src/RemoteCall/factory/api/star.ts +++ b/src/RemoteCall/factory/api/starApi.ts @@ -1,7 +1,7 @@ /* - * Filename: /home/cc/vscode-leetcode-problem-rating/src/RemoteCall/factory/api/star.ts + * Filename: /home/cc/vscode-leetcode-problem-rating/src/RemoteCall/factory/api/starApi.ts * Path: /home/cc/vscode-leetcode-problem-rating - * Created Date: Monday, November 14th 2022, 4:04:31 pm + * Created Date: Thursday, November 17th 2022, 11:44:14 am * Author: ccagml * * Copyright (c) 2022 ccagml . All rights reserved. diff --git a/src/RemoteCall/factory/api/submission.ts b/src/RemoteCall/factory/api/submissionApi.ts similarity index 100% rename from src/RemoteCall/factory/api/submission.ts rename to src/RemoteCall/factory/api/submissionApi.ts diff --git a/src/RemoteCall/factory/api/submit.ts b/src/RemoteCall/factory/api/submitApi.ts similarity index 97% rename from src/RemoteCall/factory/api/submit.ts rename to src/RemoteCall/factory/api/submitApi.ts index 4e0bae2..0eb3c60 100644 --- a/src/RemoteCall/factory/api/submit.ts +++ b/src/RemoteCall/factory/api/submitApi.ts @@ -1,7 +1,7 @@ /* - * Filename: /home/cc/vscode-leetcode-problem-rating/src/RemoteCall/factory/api/submit.ts + * Filename: /home/cc/vscode-leetcode-problem-rating/src/RemoteCall/factory/api/submitApi.ts * Path: /home/cc/vscode-leetcode-problem-rating - * Created Date: Monday, November 14th 2022, 4:04:31 pm + * Created Date: Thursday, November 17th 2022, 11:44:14 am * Author: ccagml * * Copyright (c) 2022 ccagml . All rights reserved. diff --git a/src/RemoteCall/factory/api/test.ts b/src/RemoteCall/factory/api/testApi.ts similarity index 98% rename from src/RemoteCall/factory/api/test.ts rename to src/RemoteCall/factory/api/testApi.ts index d02ff6a..d8718f8 100644 --- a/src/RemoteCall/factory/api/test.ts +++ b/src/RemoteCall/factory/api/testApi.ts @@ -1,7 +1,7 @@ /* - * Filename: /home/cc/vscode-leetcode-problem-rating/src/RemoteCall/factory/api/test.ts + * Filename: /home/cc/vscode-leetcode-problem-rating/src/RemoteCall/factory/api/testApi.ts * Path: /home/cc/vscode-leetcode-problem-rating - * Created Date: Wednesday, November 16th 2022, 3:13:59 pm + * Created Date: Thursday, November 17th 2022, 11:44:14 am * Author: ccagml * * Copyright (c) 2022 ccagml . All rights reserved. diff --git a/src/RemoteCall/factory/api/user.ts b/src/RemoteCall/factory/api/userApi.ts similarity index 98% rename from src/RemoteCall/factory/api/user.ts rename to src/RemoteCall/factory/api/userApi.ts index 1d6510c..3566626 100644 --- a/src/RemoteCall/factory/api/user.ts +++ b/src/RemoteCall/factory/api/userApi.ts @@ -1,7 +1,7 @@ /* - * Filename: /home/cc/vscode-leetcode-problem-rating/src/RemoteCall/factory/api/user.ts + * Filename: /home/cc/vscode-leetcode-problem-rating/src/RemoteCall/factory/api/userApi.ts * Path: /home/cc/vscode-leetcode-problem-rating - * Created Date: Monday, November 14th 2022, 4:04:31 pm + * Created Date: Thursday, November 17th 2022, 11:44:14 am * Author: ccagml * * Copyright (c) 2022 ccagml . All rights reserved. diff --git a/src/RemoteCall/factory/apiFactory.ts b/src/RemoteCall/factory/apiFactory.ts index a952f81..065defe 100644 --- a/src/RemoteCall/factory/apiFactory.ts +++ b/src/RemoteCall/factory/apiFactory.ts @@ -1,12 +1,12 @@ -import { cacheApi } from "./api/cache"; -import { listApi } from "./api/list"; -import { pluginApi } from "./api/plugin"; -import { queryApi } from "./api/query"; -import { showApi } from "./api/show"; -import { starApi } from "./api/star"; -import { submitApi } from "./api/submit"; -import { testApi } from "./api/test"; -import { userApi } from "./api/user"; +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 { From 60ea174b93ca4ca7168f9b127d4992e109d17962 Mon Sep 17 00:00:00 2001 From: ccagml Date: Thu, 17 Nov 2022 16:08:35 +0800 Subject: [PATCH 18/26] update --- src/{RemoteCall => rpc}/actionChain/chainManager.ts | 2 +- src/{RemoteCall => rpc}/actionChain/chainNode/cache.ts | 2 +- src/{RemoteCall => rpc}/actionChain/chainNode/core.ts | 2 +- src/{RemoteCall => rpc}/actionChain/chainNode/leetcode.cn.ts | 2 +- src/{RemoteCall => rpc}/actionChain/chainNode/leetcode.ts | 2 +- src/{RemoteCall => rpc}/actionChain/chainNode/retry.ts | 2 +- .../actionChain/chainNode/solution.discuss.ts | 2 +- src/{RemoteCall => rpc}/actionChain/chainNodeBase.ts | 0 src/{RemoteCall => rpc}/childMain.ts | 2 +- src/{RemoteCall => rpc}/factory/api/cacheApi.ts | 2 +- src/{RemoteCall => rpc}/factory/api/listApi.ts | 2 +- src/{RemoteCall => rpc}/factory/api/pluginApi.ts | 2 +- src/{RemoteCall => rpc}/factory/api/queryApi.ts | 2 +- src/{RemoteCall => rpc}/factory/api/showApi.ts | 2 +- src/{RemoteCall => rpc}/factory/api/starApi.ts | 2 +- src/{RemoteCall => rpc}/factory/api/submissionApi.ts | 2 +- src/{RemoteCall => rpc}/factory/api/submitApi.ts | 2 +- src/{RemoteCall => rpc}/factory/api/testApi.ts | 2 +- src/{RemoteCall => rpc}/factory/api/userApi.ts | 2 +- src/{RemoteCall => rpc}/factory/apiBase.ts | 2 +- src/{RemoteCall => rpc}/factory/apiFactory.ts | 0 src/{RemoteCall => rpc}/utils/ReplyUtils.ts | 2 +- src/{RemoteCall => rpc}/utils/commUtils.ts | 2 +- src/{RemoteCall => rpc}/utils/configUtils.ts | 2 +- src/{RemoteCall => rpc}/utils/queueUtils.ts | 2 +- src/{RemoteCall => rpc}/utils/sessionUtils.ts | 2 +- src/{RemoteCall => rpc}/utils/storageUtils.ts | 2 +- src/service/ExecuteService.ts | 4 ++-- 28 files changed, 27 insertions(+), 27 deletions(-) rename src/{RemoteCall => rpc}/actionChain/chainManager.ts (95%) rename src/{RemoteCall => rpc}/actionChain/chainNode/cache.ts (97%) rename src/{RemoteCall => rpc}/actionChain/chainNode/core.ts (98%) rename src/{RemoteCall => rpc}/actionChain/chainNode/leetcode.cn.ts (98%) rename src/{RemoteCall => rpc}/actionChain/chainNode/leetcode.ts (99%) rename src/{RemoteCall => rpc}/actionChain/chainNode/retry.ts (96%) rename src/{RemoteCall => rpc}/actionChain/chainNode/solution.discuss.ts (97%) rename src/{RemoteCall => rpc}/actionChain/chainNodeBase.ts (100%) rename src/{RemoteCall => rpc}/childMain.ts (97%) rename src/{RemoteCall => rpc}/factory/api/cacheApi.ts (92%) rename src/{RemoteCall => rpc}/factory/api/listApi.ts (96%) rename src/{RemoteCall => rpc}/factory/api/pluginApi.ts (95%) rename src/{RemoteCall => rpc}/factory/api/queryApi.ts (96%) rename src/{RemoteCall => rpc}/factory/api/showApi.ts (98%) rename src/{RemoteCall => rpc}/factory/api/starApi.ts (94%) rename src/{RemoteCall => rpc}/factory/api/submissionApi.ts (98%) rename src/{RemoteCall => rpc}/factory/api/submitApi.ts (97%) rename src/{RemoteCall => rpc}/factory/api/testApi.ts (98%) rename src/{RemoteCall => rpc}/factory/api/userApi.ts (98%) rename src/{RemoteCall => rpc}/factory/apiBase.ts (96%) rename src/{RemoteCall => rpc}/factory/apiFactory.ts (100%) rename src/{RemoteCall => rpc}/utils/ReplyUtils.ts (94%) rename src/{RemoteCall => rpc}/utils/commUtils.ts (96%) rename src/{RemoteCall => rpc}/utils/configUtils.ts (99%) rename src/{RemoteCall => rpc}/utils/queueUtils.ts (98%) rename src/{RemoteCall => rpc}/utils/sessionUtils.ts (98%) rename src/{RemoteCall => rpc}/utils/storageUtils.ts (99%) diff --git a/src/RemoteCall/actionChain/chainManager.ts b/src/rpc/actionChain/chainManager.ts similarity index 95% rename from src/RemoteCall/actionChain/chainManager.ts rename to src/rpc/actionChain/chainManager.ts index dd316ba..a870e20 100644 --- a/src/RemoteCall/actionChain/chainManager.ts +++ b/src/rpc/actionChain/chainManager.ts @@ -1,5 +1,5 @@ /* - * Filename: /home/cc/vscode-leetcode-problem-rating/src/RemoteCall/actionChain/chainMgr.ts + * 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 diff --git a/src/RemoteCall/actionChain/chainNode/cache.ts b/src/rpc/actionChain/chainNode/cache.ts similarity index 97% rename from src/RemoteCall/actionChain/chainNode/cache.ts rename to src/rpc/actionChain/chainNode/cache.ts index 9dbd7cb..5117064 100644 --- a/src/RemoteCall/actionChain/chainNode/cache.ts +++ b/src/rpc/actionChain/chainNode/cache.ts @@ -1,5 +1,5 @@ /* - * Filename: /home/cc/vscode-leetcode-problem-rating/src/RemoteCall/actionChain/cache.ts + * 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 diff --git a/src/RemoteCall/actionChain/chainNode/core.ts b/src/rpc/actionChain/chainNode/core.ts similarity index 98% rename from src/RemoteCall/actionChain/chainNode/core.ts rename to src/rpc/actionChain/chainNode/core.ts index f9fd3e4..9ad7738 100644 --- a/src/RemoteCall/actionChain/chainNode/core.ts +++ b/src/rpc/actionChain/chainNode/core.ts @@ -1,5 +1,5 @@ /* - * Filename: /home/cc/vscode-leetcode-problem-rating/src/RemoteCall/actionChain/core.ts + * 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 diff --git a/src/RemoteCall/actionChain/chainNode/leetcode.cn.ts b/src/rpc/actionChain/chainNode/leetcode.cn.ts similarity index 98% rename from src/RemoteCall/actionChain/chainNode/leetcode.cn.ts rename to src/rpc/actionChain/chainNode/leetcode.cn.ts index a8df828..71739d9 100644 --- a/src/RemoteCall/actionChain/chainNode/leetcode.cn.ts +++ b/src/rpc/actionChain/chainNode/leetcode.cn.ts @@ -1,5 +1,5 @@ /* - * Filename: /home/cc/vscode-leetcode-problem-rating/src/RemoteCall/actionChain/leetcode.cn.ts + * 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 diff --git a/src/RemoteCall/actionChain/chainNode/leetcode.ts b/src/rpc/actionChain/chainNode/leetcode.ts similarity index 99% rename from src/RemoteCall/actionChain/chainNode/leetcode.ts rename to src/rpc/actionChain/chainNode/leetcode.ts index 50e09cf..4f983eb 100644 --- a/src/RemoteCall/actionChain/chainNode/leetcode.ts +++ b/src/rpc/actionChain/chainNode/leetcode.ts @@ -1,5 +1,5 @@ /* - * Filename: /home/cc/vscode-leetcode-problem-rating/src/RemoteCall/actionChain/leetcode.ts + * 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 diff --git a/src/RemoteCall/actionChain/chainNode/retry.ts b/src/rpc/actionChain/chainNode/retry.ts similarity index 96% rename from src/RemoteCall/actionChain/chainNode/retry.ts rename to src/rpc/actionChain/chainNode/retry.ts index 4349c8a..26ae28c 100644 --- a/src/RemoteCall/actionChain/chainNode/retry.ts +++ b/src/rpc/actionChain/chainNode/retry.ts @@ -1,5 +1,5 @@ /* - * Filename: /home/cc/vscode-leetcode-problem-rating/src/RemoteCall/actionChain/retry.ts + * 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 diff --git a/src/RemoteCall/actionChain/chainNode/solution.discuss.ts b/src/rpc/actionChain/chainNode/solution.discuss.ts similarity index 97% rename from src/RemoteCall/actionChain/chainNode/solution.discuss.ts rename to src/rpc/actionChain/chainNode/solution.discuss.ts index 781397b..a7d5def 100644 --- a/src/RemoteCall/actionChain/chainNode/solution.discuss.ts +++ b/src/rpc/actionChain/chainNode/solution.discuss.ts @@ -1,5 +1,5 @@ /* - * Filename: /home/cc/vscode-leetcode-problem-rating/src/RemoteCall/actionChain/solution.discuss.ts + * 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 diff --git a/src/RemoteCall/actionChain/chainNodeBase.ts b/src/rpc/actionChain/chainNodeBase.ts similarity index 100% rename from src/RemoteCall/actionChain/chainNodeBase.ts rename to src/rpc/actionChain/chainNodeBase.ts diff --git a/src/RemoteCall/childMain.ts b/src/rpc/childMain.ts similarity index 97% rename from src/RemoteCall/childMain.ts rename to src/rpc/childMain.ts index 3991caf..f7e2fb9 100644 --- a/src/RemoteCall/childMain.ts +++ b/src/rpc/childMain.ts @@ -1,5 +1,5 @@ /* - * Filename: https://github.com/ccagml/vscode-leetcode-problem-rating/src/RemoteCall/cli.ts + * 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 diff --git a/src/RemoteCall/factory/api/cacheApi.ts b/src/rpc/factory/api/cacheApi.ts similarity index 92% rename from src/RemoteCall/factory/api/cacheApi.ts rename to src/rpc/factory/api/cacheApi.ts index 6d1b959..6ee082b 100644 --- a/src/RemoteCall/factory/api/cacheApi.ts +++ b/src/rpc/factory/api/cacheApi.ts @@ -1,5 +1,5 @@ /* - * Filename: /home/cc/vscode-leetcode-problem-rating/src/RemoteCall/factory/api/cacheApi.ts + * 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 diff --git a/src/RemoteCall/factory/api/listApi.ts b/src/rpc/factory/api/listApi.ts similarity index 96% rename from src/RemoteCall/factory/api/listApi.ts rename to src/rpc/factory/api/listApi.ts index f3285a7..5c5e6cb 100644 --- a/src/RemoteCall/factory/api/listApi.ts +++ b/src/rpc/factory/api/listApi.ts @@ -1,5 +1,5 @@ /* - * Filename: /home/cc/vscode-leetcode-problem-rating/src/RemoteCall/factory/api/listApi.ts + * 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 diff --git a/src/RemoteCall/factory/api/pluginApi.ts b/src/rpc/factory/api/pluginApi.ts similarity index 95% rename from src/RemoteCall/factory/api/pluginApi.ts rename to src/rpc/factory/api/pluginApi.ts index d9979c3..7712132 100644 --- a/src/RemoteCall/factory/api/pluginApi.ts +++ b/src/rpc/factory/api/pluginApi.ts @@ -1,5 +1,5 @@ /* - * Filename: /home/cc/vscode-leetcode-problem-rating/src/RemoteCall/factory/api/pluginApi.ts + * 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 diff --git a/src/RemoteCall/factory/api/queryApi.ts b/src/rpc/factory/api/queryApi.ts similarity index 96% rename from src/RemoteCall/factory/api/queryApi.ts rename to src/rpc/factory/api/queryApi.ts index be7de61..a568079 100644 --- a/src/RemoteCall/factory/api/queryApi.ts +++ b/src/rpc/factory/api/queryApi.ts @@ -1,5 +1,5 @@ /* - * Filename: /home/cc/vscode-leetcode-problem-rating/src/RemoteCall/factory/api/queryApi.ts + * 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 diff --git a/src/RemoteCall/factory/api/showApi.ts b/src/rpc/factory/api/showApi.ts similarity index 98% rename from src/RemoteCall/factory/api/showApi.ts rename to src/rpc/factory/api/showApi.ts index 2a6ee5c..e6f0b75 100644 --- a/src/RemoteCall/factory/api/showApi.ts +++ b/src/rpc/factory/api/showApi.ts @@ -1,5 +1,5 @@ /* - * Filename: /home/cc/vscode-leetcode-problem-rating/src/RemoteCall/factory/api/showApi.ts + * 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 diff --git a/src/RemoteCall/factory/api/starApi.ts b/src/rpc/factory/api/starApi.ts similarity index 94% rename from src/RemoteCall/factory/api/starApi.ts rename to src/rpc/factory/api/starApi.ts index dff35db..0842962 100644 --- a/src/RemoteCall/factory/api/starApi.ts +++ b/src/rpc/factory/api/starApi.ts @@ -1,5 +1,5 @@ /* - * Filename: /home/cc/vscode-leetcode-problem-rating/src/RemoteCall/factory/api/starApi.ts + * 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 diff --git a/src/RemoteCall/factory/api/submissionApi.ts b/src/rpc/factory/api/submissionApi.ts similarity index 98% rename from src/RemoteCall/factory/api/submissionApi.ts rename to src/rpc/factory/api/submissionApi.ts index 6c9754b..98b2684 100644 --- a/src/RemoteCall/factory/api/submissionApi.ts +++ b/src/rpc/factory/api/submissionApi.ts @@ -1,5 +1,5 @@ /* - * Filename: /home/cc/vscode-leetcode-problem-rating/src/RemoteCall/factory/api/submission.ts + * 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 diff --git a/src/RemoteCall/factory/api/submitApi.ts b/src/rpc/factory/api/submitApi.ts similarity index 97% rename from src/RemoteCall/factory/api/submitApi.ts rename to src/rpc/factory/api/submitApi.ts index 0eb3c60..9a8d61b 100644 --- a/src/RemoteCall/factory/api/submitApi.ts +++ b/src/rpc/factory/api/submitApi.ts @@ -1,5 +1,5 @@ /* - * Filename: /home/cc/vscode-leetcode-problem-rating/src/RemoteCall/factory/api/submitApi.ts + * 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 diff --git a/src/RemoteCall/factory/api/testApi.ts b/src/rpc/factory/api/testApi.ts similarity index 98% rename from src/RemoteCall/factory/api/testApi.ts rename to src/rpc/factory/api/testApi.ts index d8718f8..54bfe89 100644 --- a/src/RemoteCall/factory/api/testApi.ts +++ b/src/rpc/factory/api/testApi.ts @@ -1,5 +1,5 @@ /* - * Filename: /home/cc/vscode-leetcode-problem-rating/src/RemoteCall/factory/api/testApi.ts + * 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 diff --git a/src/RemoteCall/factory/api/userApi.ts b/src/rpc/factory/api/userApi.ts similarity index 98% rename from src/RemoteCall/factory/api/userApi.ts rename to src/rpc/factory/api/userApi.ts index 3566626..68c5b0f 100644 --- a/src/RemoteCall/factory/api/userApi.ts +++ b/src/rpc/factory/api/userApi.ts @@ -1,5 +1,5 @@ /* - * Filename: /home/cc/vscode-leetcode-problem-rating/src/RemoteCall/factory/api/userApi.ts + * 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 diff --git a/src/RemoteCall/factory/apiBase.ts b/src/rpc/factory/apiBase.ts similarity index 96% rename from src/RemoteCall/factory/apiBase.ts rename to src/rpc/factory/apiBase.ts index f36415e..7b22632 100644 --- a/src/RemoteCall/factory/apiBase.ts +++ b/src/rpc/factory/apiBase.ts @@ -1,5 +1,5 @@ /* - * Filename: /home/cc/vscode-leetcode-problem-rating/src/RemoteCall/factory/apiBase.ts + * 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 diff --git a/src/RemoteCall/factory/apiFactory.ts b/src/rpc/factory/apiFactory.ts similarity index 100% rename from src/RemoteCall/factory/apiFactory.ts rename to src/rpc/factory/apiFactory.ts diff --git a/src/RemoteCall/utils/ReplyUtils.ts b/src/rpc/utils/ReplyUtils.ts similarity index 94% rename from src/RemoteCall/utils/ReplyUtils.ts rename to src/rpc/utils/ReplyUtils.ts index b3a0332..aca9f6e 100644 --- a/src/RemoteCall/utils/ReplyUtils.ts +++ b/src/rpc/utils/ReplyUtils.ts @@ -1,5 +1,5 @@ /* - * Filename: /home/cc/vscode-leetcode-problem-rating/src/RemoteCall/Response.ts + * 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 diff --git a/src/RemoteCall/utils/commUtils.ts b/src/rpc/utils/commUtils.ts similarity index 96% rename from src/RemoteCall/utils/commUtils.ts rename to src/rpc/utils/commUtils.ts index f25fb7c..401979d 100644 --- a/src/RemoteCall/utils/commUtils.ts +++ b/src/rpc/utils/commUtils.ts @@ -1,5 +1,5 @@ /* - * Filename: /home/cc/vscode-leetcode-problem-rating/src/RemoteCall/commUtils.ts + * 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 diff --git a/src/RemoteCall/utils/configUtils.ts b/src/rpc/utils/configUtils.ts similarity index 99% rename from src/RemoteCall/utils/configUtils.ts rename to src/rpc/utils/configUtils.ts index d133cf7..7a9ce2c 100644 --- a/src/RemoteCall/utils/configUtils.ts +++ b/src/rpc/utils/configUtils.ts @@ -1,5 +1,5 @@ /* - * Filename: https://github.com/ccagml/vscode-leetcode-problem-rating/src/RemoteCall/config.ts + * 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 diff --git a/src/RemoteCall/utils/queueUtils.ts b/src/rpc/utils/queueUtils.ts similarity index 98% rename from src/RemoteCall/utils/queueUtils.ts rename to src/rpc/utils/queueUtils.ts index 07775aa..d969b41 100644 --- a/src/RemoteCall/utils/queueUtils.ts +++ b/src/rpc/utils/queueUtils.ts @@ -1,5 +1,5 @@ /* - * Filename: https://github.com/ccagml/vscode-leetcode-problem-rating/src/RemoteCall/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 diff --git a/src/RemoteCall/utils/sessionUtils.ts b/src/rpc/utils/sessionUtils.ts similarity index 98% rename from src/RemoteCall/utils/sessionUtils.ts rename to src/rpc/utils/sessionUtils.ts index 521468e..01120ae 100644 --- a/src/RemoteCall/utils/sessionUtils.ts +++ b/src/rpc/utils/sessionUtils.ts @@ -1,5 +1,5 @@ /* - * Filename: https://github.com/ccagml/vscode-leetcode-problem-rating/src/RemoteCall/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 diff --git a/src/RemoteCall/utils/storageUtils.ts b/src/rpc/utils/storageUtils.ts similarity index 99% rename from src/RemoteCall/utils/storageUtils.ts rename to src/rpc/utils/storageUtils.ts index 47b95b6..913f73a 100644 --- a/src/RemoteCall/utils/storageUtils.ts +++ b/src/rpc/utils/storageUtils.ts @@ -1,5 +1,5 @@ /* - * Filename: https://github.com/ccagml/vscode-leetcode-problem-rating/src/RemoteCall/storageUtils.ts + * 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 diff --git a/src/service/ExecuteService.ts b/src/service/ExecuteService.ts index 070450b..6b2de70 100644 --- a/src/service/ExecuteService.ts +++ b/src/service/ExecuteService.ts @@ -39,7 +39,7 @@ class ExecuteService implements Disposable { private configurationChangeListener: Disposable; constructor() { - // this.leetCodeCliResourcesRootPath = path.join(__dirname, "..", "..", "node_modules", "RemoteCall"); + // this.leetCodeCliResourcesRootPath = path.join(__dirname, "..", "..", "node_modules", "rpc"); if (!systemUtils.useVscodeNode()) { this.leetCodeCliResourcesRootPath = path.join( __dirname, @@ -56,7 +56,7 @@ class ExecuteService implements Disposable { "..", "out", "src", - "RemoteCall" + "rpc" ); this.nodeExecutable = this.initNodePath(); this.configurationChangeListener = workspace.onDidChangeConfiguration( From ea95036af5beeb5bf972d5b6bbaa3b3b697a8a3e Mon Sep 17 00:00:00 2001 From: ccagml Date: Fri, 18 Nov 2022 09:41:32 +0800 Subject: [PATCH 19/26] =?UTF-8?q?=E6=9B=B4=E6=94=B9=E6=A8=A1=E6=9D=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- resources/templates/codeonly.tpl | 27 ++++-- resources/templates/detailed.tpl | 50 ++++++---- src/controller/TreeViewController.ts | 32 +++++++ src/extension.ts | 5 + src/rpc/actionChain/chainNode/core.ts | 3 + src/rpc/utils/storageUtils.ts | 75 ++++++++++++++- src/service/FileButtonService.ts | 131 +++++++++++++++++++------- 7 files changed, 257 insertions(+), 66 deletions(-) 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/controller/TreeViewController.ts b/src/controller/TreeViewController.ts index 3500b0c..577466f 100644 --- a/src/controller/TreeViewController.ts +++ b/src/controller/TreeViewController.ts @@ -298,6 +298,38 @@ class TreeViewController implements Disposable { } } + 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 usingCmd(): boolean { const comSpec: string | undefined = process.env.ComSpec; // 'cmd.exe' is used as a fallback if process.env.ComSpec is unavailable. diff --git a/src/extension.ts b/src/extension.ts index f20045c..1b5ff31 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -97,6 +97,11 @@ export async function activate(context: ExtensionContext): Promise { (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) ), diff --git a/src/rpc/actionChain/chainNode/core.ts b/src/rpc/actionChain/chainNode/core.ts index 9ad7738..18677b9 100644 --- a/src/rpc/actionChain/chainNode/core.ts +++ b/src/rpc/actionChain/chainNode/core.ts @@ -88,6 +88,9 @@ class CorePlugin extends ChainNodeBase { exportProblem = (problem, opts) => { const data = _.extend({}, problem); + // 增加版本信息 + data.LCPTCTX = configUtils.LCPTCTX; + data.allCaseList = storageUtils.getAllCase(problem.desc); // unify format before rendering data.app = configUtils.app || "leetcode"; diff --git a/src/rpc/utils/storageUtils.ts b/src/rpc/utils/storageUtils.ts index 913f73a..7e57178 100644 --- a/src/rpc/utils/storageUtils.ts +++ b/src/rpc/utils/storageUtils.ts @@ -161,10 +161,6 @@ class StorageUtils { } public init() { - _.templateSettings = { - evaluate: /\{\{(.+?)\}\}/g, - interpolate: /\$\{(.+?)\}/g, - }; this.mkdir(this.homeDir()); this.initCache(); } @@ -330,6 +326,76 @@ class StorageUtils { return data; } + /** + * name + */ + public getAllCase(new_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(/^ /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("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("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( @@ -337,6 +403,7 @@ class StorageUtils { "..", "..", "..", + "..", "resources", "templates", tpl + ".tpl" diff --git a/src/service/FileButtonService.ts b/src/service/FileButtonService.ts index bc79acd..321fdc6 100644 --- a/src/service/FileButtonService.ts +++ b/src/service/FileButtonService.ts @@ -24,34 +24,12 @@ export class FileButtonService implements vscode.CodeLensProvider { this.onDidChangeCodeLensesEmitter.fire(); } - public provideCodeLenses( - document: vscode.TextDocument - ): vscode.ProviderResult { + // 处理代码的按钮 + private processCodeButton(codeLensLine, document, node): vscode.CodeLens[] { + const temp_result: vscode.CodeLens[] = []; 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; - } + return temp_result; } const range: vscode.Range = new vscode.Range( @@ -60,10 +38,9 @@ export class FileButtonService implements vscode.CodeLensProvider { codeLensLine, 0 ); - const codeLens: vscode.CodeLens[] = []; if (shortcuts.indexOf("submit") >= 0) { - codeLens.push( + temp_result.push( new vscode.CodeLens(range, { title: "Submit", command: "leetcode.submitSolution", @@ -73,7 +50,7 @@ export class FileButtonService implements vscode.CodeLensProvider { } if (shortcuts.indexOf("case") >= 0) { - codeLens.push( + temp_result.push( new vscode.CodeLens(range, { title: "case", command: "leetcode.testSolutionDefault", @@ -82,7 +59,7 @@ export class FileButtonService implements vscode.CodeLensProvider { ); } if (shortcuts.indexOf("allcase") >= 0) { - codeLens.push( + temp_result.push( new vscode.CodeLens(range, { title: "allcase", command: "leetcode.testSolutionDefault", @@ -92,7 +69,7 @@ export class FileButtonService implements vscode.CodeLensProvider { } if (shortcuts.indexOf("test") >= 0) { - codeLens.push( + temp_result.push( new vscode.CodeLens(range, { title: "Test", command: "leetcode.testSolution", @@ -102,7 +79,7 @@ export class FileButtonService implements vscode.CodeLensProvider { } if (shortcuts.indexOf("star") >= 0 && node) { - codeLens.push( + temp_result.push( new vscode.CodeLens(range, { title: node.isFavorite ? "Unstar" : "Star", command: node.isFavorite @@ -114,7 +91,7 @@ export class FileButtonService implements vscode.CodeLensProvider { } if (shortcuts.indexOf("solution") >= 0) { - codeLens.push( + temp_result.push( new vscode.CodeLens(range, { title: "Solution", command: "leetcode.showSolution", @@ -124,7 +101,7 @@ export class FileButtonService implements vscode.CodeLensProvider { } if (shortcuts.indexOf("description") >= 0) { - codeLens.push( + temp_result.push( new vscode.CodeLens(range, { title: "Description", command: "leetcode.previewProblem", @@ -132,6 +109,92 @@ export class FileButtonService implements vscode.CodeLensProvider { }) ); } + 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(/" "/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; } From 86ba0e7612a27d1eed182a75e5358999b04745a8 Mon Sep 17 00:00:00 2001 From: ccagml Date: Fri, 18 Nov 2022 11:47:34 +0800 Subject: [PATCH 20/26] area case --- hot.sh | 2 + src/rpc/factory/api/testApi.ts | 78 +++++++------------------------ src/rpc/utils/storageUtils.ts | 80 ++++++++++++++++++++++++++------ src/service/FileButtonService.ts | 2 +- 4 files changed, 84 insertions(+), 78 deletions(-) create mode 100755 hot.sh 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/src/rpc/factory/api/testApi.ts b/src/rpc/factory/api/testApi.ts index 54bfe89..f6b3ea0 100644 --- a/src/rpc/factory/api/testApi.ts +++ b/src/rpc/factory/api/testApi.ts @@ -112,71 +112,25 @@ class TestApi extends ApiBase { } if (argv.allcase) { + let temp_test_set: Set = new Set(); + 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(/^ /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("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("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 = ""; - } - } + 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); + }); } - if (temp_test.length < 1) { - return; - } + let temp_test: Array = []; + temp_test_set.forEach((x) => { + temp_test.push(x); + }); + let all_case = temp_test.join("\n"); problem.testcase = all_case; } diff --git a/src/rpc/utils/storageUtils.ts b/src/rpc/utils/storageUtils.ts index 7e57178..5286cba 100644 --- a/src/rpc/utils/storageUtils.ts +++ b/src/rpc/utils/storageUtils.ts @@ -18,6 +18,7 @@ export interface IMETA { id: string; fid: string; lang: string; + writeCase: Array; } //Object.assign({}, defaultMETA, {}) @@ -25,6 +26,7 @@ export const defaultMETA: IMETA = { id: "", fid: "", lang: "", + writeCase: [], }; class StorageUtils { @@ -329,14 +331,14 @@ class StorageUtils { /** * name */ - public getAllCase(new_desc) { - new_desc = new_desc.replace(/<\/sup>/gm, "").replace(//gm, "^"); + 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, "⁠"); + 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; @@ -421,20 +423,68 @@ class StorageUtils { 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, {}); - 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; + + 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; } } diff --git a/src/service/FileButtonService.ts b/src/service/FileButtonService.ts index 321fdc6..134a97c 100644 --- a/src/service/FileButtonService.ts +++ b/src/service/FileButtonService.ts @@ -182,7 +182,7 @@ export class FileButtonService implements vscode.CodeLensProvider { .replace(/#/g, "") .replace(/\/\//g, "") .replace(/--/g, "") - .replace(/" "/g, ""); + .replace(/\s+/g, ""); } // 收集所有用例 if (lineContent.indexOf("@lcpr case=start") >= 0) { From 53caec5badc6554ccf3a9554bc7db6933c29d6ef Mon Sep 17 00:00:00 2001 From: ccagml Date: Fri, 18 Nov 2022 14:22:30 +0800 Subject: [PATCH 21/26] format --- .eslintrc.js | 2 + src/controller/FileButtonController.ts | 30 +- src/controller/LoginController.ts | 68 +- src/controller/TreeViewController.ts | 581 +-- src/dao/choiceDao.ts | 301 +- src/dao/tagsDao.ts | 3422 +++-------------- src/extension.ts | 91 +- src/model/NodeModel.ts | 14 +- src/rpc/actionChain/chainManager.ts | 4 +- src/rpc/actionChain/chainNode/cache.ts | 5 +- src/rpc/actionChain/chainNode/core.ts | 15 +- src/rpc/actionChain/chainNode/leetcode.cn.ts | 25 +- src/rpc/actionChain/chainNode/leetcode.ts | 110 +- .../actionChain/chainNode/solution.discuss.ts | 12 +- src/rpc/factory/api/cacheApi.ts | 5 +- src/rpc/factory/api/showApi.ts | 24 +- src/rpc/factory/api/starApi.ts | 24 +- src/rpc/factory/api/submitApi.ts | 12 +- src/rpc/factory/api/testApi.ts | 7 +- src/rpc/factory/api/userApi.ts | 19 +- src/rpc/utils/commUtils.ts | 3 +- src/rpc/utils/configUtils.ts | 21 +- src/rpc/utils/queueUtils.ts | 3 +- src/rpc/utils/sessionUtils.ts | 5 +- src/rpc/utils/storageUtils.ts | 19 +- src/service/BaseWebviewService.ts | 34 +- src/service/ExecuteService.ts | 280 +- src/service/FileButtonService.ts | 39 +- src/service/MarkdownService.ts | 78 +- src/service/PreviewService.ts | 38 +- src/service/StatusBarService.ts | 41 +- src/service/SubmissionService.ts | 17 +- src/service/TreeDataService.ts | 22 +- src/service/TreeItemDecorationService.ts | 7 +- src/utils/CliUtils.ts | 118 +- src/utils/ConfigUtils.ts | 40 +- src/utils/OutputUtils.ts | 50 +- src/utils/SystemUtils.ts | 20 +- 38 files changed, 1104 insertions(+), 4502 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index d310ceb..2be3590 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -60,6 +60,8 @@ module.exports = { "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: [ diff --git a/src/controller/FileButtonController.ts b/src/controller/FileButtonController.ts index b6c2fca..a40764b 100644 --- a/src/controller/FileButtonController.ts +++ b/src/controller/FileButtonController.ts @@ -7,12 +7,7 @@ * Copyright (c) 2022 ccagml . All rights reserved. */ -import { - ConfigurationChangeEvent, - Disposable, - languages, - workspace, -} from "vscode"; +import { ConfigurationChangeEvent, Disposable, languages, workspace } from "vscode"; import { fileButtonService } from "../service/FileButtonService"; // 文件按钮的控制器 class FileButtonController implements Disposable { @@ -20,21 +15,13 @@ class FileButtonController implements Disposable { private configurationChangeListener: Disposable; constructor() { - this.configurationChangeListener = workspace.onDidChangeConfiguration( - (event: ConfigurationChangeEvent) => { - if ( - event.affectsConfiguration("leetcode-problem-rating.editor.shortcuts") - ) { - fileButtonService.refresh(); - } - }, - this - ); + 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 { @@ -45,5 +32,4 @@ class FileButtonController implements Disposable { } } -export const fileButtonController: FileButtonController = - new FileButtonController(); +export const fileButtonController: FileButtonController = new FileButtonController(); diff --git a/src/controller/LoginController.ts b/src/controller/LoginController.ts index bf8d90d..09b5184 100644 --- a/src/controller/LoginController.ts +++ b/src/controller/LoginController.ts @@ -10,13 +10,7 @@ import * as cp from "child_process"; import * as systemUtils from "../utils/SystemUtils"; import { executeService } from "../service/ExecuteService"; -import { - DialogType, - Endpoint, - IQuickItemEx, - loginArgsMapping, - UserStatus, -} from "../model/Model"; +import { DialogType, Endpoint, IQuickItemEx, loginArgsMapping, UserStatus } from "../model/Model"; import { createEnvOption } from "../utils/CliUtils"; import { logOutput, promptForOpenOutputChannel } from "../utils/OutputUtils"; import { eventService } from "../service/EventService"; @@ -64,10 +58,7 @@ class LoginContorller { value: "Cookie", } ); - const choice: IQuickItemEx | undefined = await window.showQuickPick( - picks, - qpOpiton - ); + const choice: IQuickItemEx | undefined = await window.showQuickPick(picks, qpOpiton); if (!choice) { return; } @@ -80,40 +71,26 @@ class LoginContorller { 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(); + 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(), - } - ); + 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 } - ); + 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 = cp.spawn(executeService.node, [leetCodeBinaryPath, "user", commandArg], { + shell: true, + env: createEnvOption(), + }); } } @@ -150,9 +127,7 @@ class LoginContorller { } }); - childProc.stderr?.on("data", (data: string | Buffer) => - logOutput.append(data.toString()) - ); + childProc.stderr?.on("data", (data: string | Buffer) => logOutput.append(data.toString())); childProc.on("error", reject); const name: string | undefined = await window.showInputBox({ @@ -171,11 +146,7 @@ class LoginContorller { password: true, ignoreFocusOut: true, validateInput: (s: string): string | undefined => - s - ? undefined - : isByCookie - ? "Cookie must not be empty" - : "Password must not be empty", + s ? undefined : isByCookie ? "Cookie must not be empty" : "Password must not be empty", }); if (!pwd) { childProc.kill(); @@ -189,10 +160,7 @@ class LoginContorller { window.showInformationMessage(`${inMessage} 成功`); } } catch (error) { - promptForOpenOutputChannel( - `${inMessage}失败. 请看看控制台输出信息`, - DialogType.error - ); + promptForOpenOutputChannel(`${inMessage}失败. 请看看控制台输出信息`, DialogType.error); } } diff --git a/src/controller/TreeViewController.ts b/src/controller/TreeViewController.ts index 577466f..2122112 100644 --- a/src/controller/TreeViewController.ts +++ b/src/controller/TreeViewController.ts @@ -12,14 +12,7 @@ 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 { Disposable, Uri, window, QuickPickItem, workspace, WorkspaceConfiguration } from "vscode"; import { SearchNode, userContestRankingObj, @@ -62,18 +55,10 @@ import { statusBarService } from "../service/StatusBarService"; import { previewService } from "../service/PreviewService"; import { executeService } from "../service/ExecuteService"; import { getNodeIdFromFile } from "../utils/SystemUtils"; -import { - logOutput, - promptForOpenOutputChannel, - promptForSignIn, - promptHintMessage, -} from "../utils/OutputUtils"; +import { logOutput, promptForOpenOutputChannel, promptForSignIn, promptHintMessage } from "../utils/OutputUtils"; import { treeDataService } from "../service/TreeDataService"; import { genFileExt, genFileName } from "../utils/SystemUtils"; -import { - IDescriptionConfiguration, - isStarShortcut, -} from "../utils/ConfigUtils"; +import { IDescriptionConfiguration, isStarShortcut } from "../utils/ConfigUtils"; import * as systemUtils from "../utils/SystemUtils"; import { solutionService } from "../service/SolutionService"; import { eventService } from "../service/EventService"; @@ -87,10 +72,7 @@ import { getVsCodeConfig, getWorkspaceFolder } from "../utils/ConfigUtils"; // 视图控制器 class TreeViewController implements Disposable { - private explorerNodeMap: Map = new Map< - string, - NodeModel - >(); + private explorerNodeMap: Map = new Map(); private companySet: Set = new Set(); private tagSet: Set = new Set(); private searchSet: Map = new Map(); @@ -98,9 +80,7 @@ class TreeViewController implements Disposable { private waitUserContest: boolean; // 获取当前文件的路径 - public async getActiveFilePath( - uri?: vscode.Uri - ): Promise { + public async getActiveFilePath(uri?: vscode.Uri): Promise { let textEditor: vscode.TextEditor | undefined; if (uri) { textEditor = await vscode.window.showTextDocument(uri, { @@ -139,10 +119,7 @@ class TreeViewController implements Disposable { submissionService.show(result); eventService.emit("submit", submissionService.getSubmitEvent()); } catch (error) { - await promptForOpenOutputChannel( - "提交出错了. 请查看控制台信息~", - DialogType.error - ); + await promptForOpenOutputChannel("提交出错了. 请查看控制台信息~", DialogType.error); return; } @@ -187,8 +164,7 @@ class TreeViewController implements Disposable { // value: ":alldefault", // }, ); - const choice: IQuickItemEx | undefined = - await vscode.window.showQuickPick(picks); + const choice: IQuickItemEx | undefined = await vscode.window.showQuickPick(picks); if (!choice) { return; } @@ -209,27 +185,20 @@ class TreeViewController implements Disposable { ignoreFocusOut: true, }); if (testString) { - result = await executeService.testSolution( - filePath, - this.parseTestString(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(); + 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." - ); + vscode.window.showErrorMessage("The selected test file must not be empty."); } } break; @@ -245,17 +214,11 @@ class TreeViewController implements Disposable { submissionService.show(result); eventService.emit("submit", submissionService.getSubmitEvent()); } catch (error) { - await promptForOpenOutputChannel( - "提交测试出错了. 请查看控制台信息~", - DialogType.error - ); + await promptForOpenOutputChannel("提交测试出错了. 请查看控制台信息~", DialogType.error); } } - public async showFileSelectDialog( - fsPath?: string - ): Promise { - const defaultUri: vscode.Uri | undefined = - this.getBelongingWorkspaceFolderUri(fsPath); + public async showFileSelectDialog(fsPath?: string): Promise { + const defaultUri: vscode.Uri | undefined = this.getBelongingWorkspaceFolderUri(fsPath); const options: vscode.OpenDialogOptions = { defaultUri, canSelectFiles: true, @@ -266,10 +229,7 @@ class TreeViewController implements Disposable { return await vscode.window.showOpenDialog(options); } - public async testSolutionDefault( - uri?: vscode.Uri, - allCase?: boolean - ): Promise { + public async testSolutionDefault(uri?: vscode.Uri, allCase?: boolean): Promise { try { if (statusBarService.getStatus() === UserStatus.SignedOut) { return; @@ -280,28 +240,18 @@ class TreeViewController implements Disposable { return; } - let result: string | undefined = await executeService.testSolution( - filePath, - undefined, - allCase || false - ); + 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 - ); + await promptForOpenOutputChannel("提交测试出错了. 请查看控制台信息~", DialogType.error); } } - public async testSolutionArea( - uri?: vscode.Uri, - testcase?: string - ): Promise { + public async testSolutionArea(uri?: vscode.Uri, testcase?: string): Promise { try { if (statusBarService.getStatus() === UserStatus.SignedOut) { return; @@ -312,21 +262,14 @@ class TreeViewController implements Disposable { return; } - let result: string | undefined = await executeService.testSolution( - filePath, - testcase, - false - ); + 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 - ); + await promptForOpenOutputChannel("提交测试出错了. 请查看控制台信息~", DialogType.error); } } @@ -384,25 +327,18 @@ class TreeViewController implements Disposable { value: Endpoint.LeetCodeCN, } ); - const choice: IQuickItemEx | undefined = - await vscode.window.showQuickPick(picks); + 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"); + 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}` - ); + vscode.window.showInformationMessage(`Switched the endpoint to ${endpoint}`); } catch (error) { - await promptForOpenOutputChannel( - "切换站点出错. 请查看控制台信息~", - DialogType.error - ); + await promptForOpenOutputChannel("切换站点出错. 请查看控制台信息~", DialogType.error); } try { @@ -410,10 +346,7 @@ class TreeViewController implements Disposable { await executeService.deleteCache(); await promptForSignIn(); } catch (error) { - await promptForOpenOutputChannel( - "登录失败. 请查看控制台信息~", - DialogType.error - ); + await promptForOpenOutputChannel("登录失败. 请查看控制台信息~", DialogType.error); } } @@ -429,8 +362,7 @@ class TreeViewController implements Disposable { }) ); - const choice: IQuickItemEx | undefined = - await vscode.window.showQuickPick(picks); + const choice: IQuickItemEx | undefined = await vscode.window.showQuickPick(picks); if (!choice || choice.value === currentStrategy) { return; } @@ -447,10 +379,7 @@ class TreeViewController implements Disposable { fileButtonService.refresh(); } } catch (error) { - await promptForOpenOutputChannel( - "添加喜欢题目失败. 请查看控制台信息~", - DialogType.error - ); + await promptForOpenOutputChannel("添加喜欢题目失败. 请查看控制台信息~", DialogType.error); } } @@ -462,10 +391,7 @@ class TreeViewController implements Disposable { fileButtonService.refresh(); } } catch (error) { - await promptForOpenOutputChannel( - "移除喜欢题目失败. 请查看控制台信息~", - DialogType.error - ); + await promptForOpenOutputChannel("移除喜欢题目失败. 请查看控制台信息~", DialogType.error); } } @@ -477,10 +403,7 @@ class TreeViewController implements Disposable { const showLockedFlag: boolean = isShowLocked(); const useEndpointTranslation: boolean = isUseEndpointTranslation(); - const result: string = await executeService.listProblems( - showLockedFlag, - useEndpointTranslation - ); + const result: string = await executeService.listProblems(showLockedFlag, useEndpointTranslation); const all_problem_info = JSON.parse(result); const problems: IProblem[] = []; const AllScoreData = treeDataService.getScoreData(); @@ -507,10 +430,7 @@ class TreeViewController implements Disposable { } return problems.reverse(); } catch (error) { - await promptForOpenOutputChannel( - "获取题目失败. 请查看控制台信息~", - DialogType.error - ); + await promptForOpenOutputChannel("获取题目失败. 请查看控制台信息~", DialogType.error); return []; } } @@ -536,17 +456,13 @@ class TreeViewController implements Disposable { } public async switchDefaultLanguage(): Promise { - const leetCodeConfig: WorkspaceConfiguration = workspace.getConfiguration( - "leetcode-problem-rating" - ); - const defaultLanguage: string | undefined = - leetCodeConfig.get("defaultLanguage"); + 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, + description: defaultLanguage === language ? "Currently used" : undefined, }); } // Put the default language at the top of the list @@ -559,23 +475,16 @@ class TreeViewController implements Disposable { return a.label.localeCompare(b.label); }); - const selectedItem: QuickPickItem | undefined = await window.showQuickPick( - languageItems, - { - placeHolder: "请设置默认语言", - ignoreFocusOut: true, - } - ); + const selectedItem: QuickPickItem | undefined = await window.showQuickPick(languageItems, { + placeHolder: "请设置默认语言", + ignoreFocusOut: true, + }); if (!selectedItem) { return; } - leetCodeConfig.update( - "defaultLanguage", - selectedItem.label, - true /* Global */ - ); + leetCodeConfig.update("defaultLanguage", selectedItem.label, true /* Global */); window.showInformationMessage(`设置默认语言 ${selectedItem.label} 成功`); } @@ -601,15 +510,13 @@ class TreeViewController implements Disposable { value: ":browse", } ); - const choice: IQuickItemEx | undefined = - await vscode.window.showQuickPick(picks, { - placeHolder: "Select where you would like to save your LeetCode files", - }); + 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(); + const directory: vscode.Uri[] | undefined = await this.showDirectorySelectDialog(); if (!directory || directory.length < 1) { result = ""; } else { @@ -619,20 +526,13 @@ class TreeViewController implements Disposable { result = choice.value; } - getVsCodeConfig().update( - "workspaceFolder", - result, - vscode.ConfigurationTarget.Global - ); + getVsCodeConfig().update("workspaceFolder", result, vscode.ConfigurationTarget.Global); return result; } - public async showDirectorySelectDialog( - fsPath?: string - ): Promise { - const defaultUri: vscode.Uri | undefined = - this.getBelongingWorkspaceFolderUri(fsPath); + public async showDirectorySelectDialog(fsPath?: string): Promise { + const defaultUri: vscode.Uri | undefined = this.getBelongingWorkspaceFolderUri(fsPath); const options: vscode.OpenDialogOptions = { defaultUri, canSelectFiles: false, @@ -643,13 +543,12 @@ class TreeViewController implements Disposable { return await vscode.window.showOpenDialog(options); } - public getBelongingWorkspaceFolderUri( - fsPath: string | undefined - ): vscode.Uri | undefined { + 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)); + const workspaceFolder: vscode.WorkspaceFolder | undefined = vscode.workspace.getWorkspaceFolder( + vscode.Uri.file(fsPath) + ); if (workspaceFolder) { defaultUri = workspaceFolder.uri; } @@ -697,8 +596,9 @@ class TreeViewController implements Disposable { // value: `userContest`, // } ); - const choice: IQuickItemEx | undefined = - await vscode.window.showQuickPick(picks, { title: "选择查询选项" }); + const choice: IQuickItemEx | undefined = await vscode.window.showQuickPick(picks, { + title: "选择查询选项", + }); if (!choice) { return; } @@ -738,9 +638,7 @@ class TreeViewController implements Disposable { } if (!problemInput) { - vscode.window.showErrorMessage( - "Invalid input to fetch the solution data." - ); + vscode.window.showErrorMessage("Invalid input to fetch the solution data."); return; } @@ -750,18 +648,11 @@ class TreeViewController implements Disposable { } try { const needTranslation: boolean = isUseEndpointTranslation(); - const solution: string = await executeService.showSolution( - problemInput, - language, - needTranslation - ); + 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 - ); + await promptForOpenOutputChannel("Failed to fetch the top voted solution. 请查看控制台信息~", DialogType.error); } } @@ -774,8 +665,7 @@ class TreeViewController implements Disposable { 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", + validateInput: (s: string): string | undefined => (s && s.trim() ? undefined : "The input must not be empty"), }); // vscode.window.showErrorMessage(twoFactor || "输入错误"); @@ -784,10 +674,7 @@ class TreeViewController implements Disposable { console.log(query_result); } catch (error) { logOutput.appendLine(error.toString()); - await promptForOpenOutputChannel( - "Failed to fetch today question. 请查看控制台信息~", - DialogType.error - ); + await promptForOpenOutputChannel("Failed to fetch today question. 请查看控制台信息~", DialogType.error); } } @@ -796,15 +683,14 @@ class TreeViewController implements Disposable { promptForSignIn(); return; } - const choice: IQuickItemEx | undefined = - await vscode.window.showQuickPick( - this.parseProblemsToPicks(this.listProblems()), - { - matchOnDetail: true, - matchOnDescription: true, - placeHolder: "Select one problem", - } - ); + const choice: IQuickItemEx | undefined = await vscode.window.showQuickPick( + this.parseProblemsToPicks(this.listProblems()), + { + matchOnDetail: true, + matchOnDescription: true, + placeHolder: "Select one problem", + } + ); if (!choice) { return; } @@ -831,16 +717,12 @@ class TreeViewController implements Disposable { 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 - ) { + 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)]; + randomProblem = temp_problems[Math.floor(Math.random() * temp_problems.length)]; } else { randomProblem = problems[Math.floor(Math.random() * problems.length)]; } @@ -850,10 +732,8 @@ class TreeViewController implements Disposable { } public async fetchProblemLanguage(): Promise { - const leetCodeConfig: vscode.WorkspaceConfiguration = - vscode.workspace.getConfiguration("leetcode-problem-rating"); - let defaultLanguage: string | undefined = - leetCodeConfig.get("defaultLanguage"); + 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; } @@ -865,30 +745,17 @@ class TreeViewController implements Disposable { })); // 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 (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 */ - ); + leetCodeConfig.update("defaultLanguage", language, true /* UserSetting */); } else if (choice === DialogOptions.never) { - leetCodeConfig.update( - "hint.setDefaultLanguage", - false, - true /* UserSetting */ - ); + leetCodeConfig.update("hint.setDefaultLanguage", false, true /* UserSetting */); } } })(); @@ -921,8 +788,7 @@ class TreeViewController implements Disposable { OpenOption.addToWorkspace, ], { - placeHolder: - "The LeetCode workspace folder is not opened in VS Code, would you like to open it?", + placeHolder: "The LeetCode workspace folder is not opened in VS Code, would you like to open it?", } ); @@ -931,34 +797,22 @@ class TreeViewController implements Disposable { case OpenOption.justOpenFile: return workspaceFolderSetting; case OpenOption.openInCurrentWindow: - await vscode.commands.executeCommand( - "vscode.openFolder", - vscode.Uri.file(workspaceFolderSetting), - false - ); + 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 - ); + 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) } - ); + vscode.workspace.updateWorkspaceFolders(vscode.workspace.workspaceFolders?.length ?? 0, 0, { + uri: vscode.Uri.file(workspaceFolderSetting), + }); break; default: return ""; } } - return systemUtils.useWsl() - ? systemUtils.toWslPath(workspaceFolderSetting) - : workspaceFolderSetting; + return systemUtils.useWsl() ? systemUtils.toWslPath(workspaceFolderSetting) : workspaceFolderSetting; } public async showProblemInternal(node: IProblem): Promise { @@ -976,16 +830,12 @@ class TreeViewController implements Disposable { } const fileFolder: string = leetCodeConfig - .get( - `filePath.${language}.folder`, - leetCodeConfig.get(`filePath.default.folder`, "") - ) + .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) + leetCodeConfig.get(`filePath.default.filename`) || genFileName(node, language) ) .trim(); @@ -999,21 +849,12 @@ class TreeViewController implements Disposable { } } - finalPath = systemUtils.useWsl() - ? await systemUtils.toWinPath(finalPath) - : finalPath; + finalPath = systemUtils.useWsl() ? await systemUtils.toWinPath(finalPath) : finalPath; - const descriptionConfig: IDescriptionConfiguration = - getDescriptionConfiguration(); + const descriptionConfig: IDescriptionConfiguration = getDescriptionConfiguration(); const needTranslation: boolean = isUseEndpointTranslation(); - await executeService.showProblem( - node, - language, - finalPath, - descriptionConfig.showInComment, - needTranslation - ); + await executeService.showProblem(node, language, finalPath, descriptionConfig.showInComment, needTranslation); const promises: any[] = [ vscode.window.showTextDocument(vscode.Uri.file(finalPath), { preview: false, @@ -1023,8 +864,7 @@ class TreeViewController implements Disposable { "hint.commentDescription", 'You can config how to show the problem description through "leetcode-problem-rating.showDescription".', "Open settings", - (): Promise => - openSettingsEditor("leetcode-problem-rating.showDescription") + (): Promise => openSettingsEditor("leetcode-problem-rating.showDescription") ), ]; if (descriptionConfig.showInWebview) { @@ -1033,10 +873,7 @@ class TreeViewController implements Disposable { await Promise.all(promises); } catch (error) { - await promptForOpenOutputChannel( - `${error} 请查看控制台信息~`, - DialogType.error - ); + await promptForOpenOutputChannel(`${error} 请查看控制台信息~`, DialogType.error); } } @@ -1044,26 +881,18 @@ class TreeViewController implements Disposable { return this.previewProblem(node, enableSideMode()); } - public async previewProblem( - input: IProblem | Uri, - isSideMode: boolean = false - ): Promise { + 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}.` - ); + window.showErrorMessage(`Failed to resolve the problem id from file: ${activeFilePath}.`); return; } - const cachedNode: IProblem | undefined = - treeViewController.getNodeById(id); + const cachedNode: IProblem | undefined = treeViewController.getNodeById(id); if (!cachedNode) { - window.showErrorMessage( - `Failed to resolve the problem with id: ${id}.` - ); + window.showErrorMessage(`Failed to resolve the problem with id: ${id}.`); return; } node = cachedNode; @@ -1073,10 +902,7 @@ class TreeViewController implements Disposable { node = input; } const needTranslation: boolean = isUseEndpointTranslation(); - const descString: string = await executeService.getDescription( - node.qid, - needTranslation - ); + const descString: string = await executeService.getDescription(node.qid, needTranslation); previewService.show(descString, node, isSideMode); } @@ -1084,8 +910,7 @@ class TreeViewController implements Disposable { 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", + validateInput: (s: string): string | undefined => (s && s.trim() ? undefined : "The input must not be empty"), }); // vscode.window.showErrorMessage(twoFactor || "输入错误"); @@ -1102,8 +927,7 @@ class TreeViewController implements Disposable { 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", + validateInput: (s: string): string | undefined => (s && s.trim() ? undefined : "The input must not be empty"), }); // vscode.window.showErrorMessage(twoFactor || "输入错误"); @@ -1123,23 +947,13 @@ class TreeViewController implements Disposable { } try { const needTranslation: boolean = isUseEndpointTranslation(); - const solution: string = await executeService.getUserContest( - needTranslation, - statusBarService.getUser() || "" - ); + const solution: string = await executeService.getUserContest(needTranslation, statusBarService.getUser() || ""); const query_result = JSON.parse(solution); - const tt: userContestRanKingBase = Object.assign( - {}, - userContestRankingObj, - query_result.userContestRanking - ); + 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 - ); + await promptForOpenOutputChannel("Failed to fetch today question. 请查看控制台信息~", DialogType.error); } } public async searchToday(): Promise { @@ -1149,9 +963,7 @@ class TreeViewController implements Disposable { } try { const needTranslation: boolean = isUseEndpointTranslation(); - const solution: string = await executeService.getTodayQuestion( - needTranslation - ); + 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 @@ -1168,42 +980,27 @@ class TreeViewController implements Disposable { } } catch (error) { logOutput.appendLine(error.toString()); - await promptForOpenOutputChannel( - "Failed to fetch today question. 请查看控制台信息~", - DialogType.error - ); + await promptForOpenOutputChannel("Failed to fetch today question. 请查看控制台信息~", DialogType.error); } } - 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 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 { @@ -1217,11 +1014,7 @@ class TreeViewController implements Disposable { } } - public async resolveRelativePath( - relativePath: string, - node: IProblem, - selectedLanguage: string - ): Promise { + public async resolveRelativePath(relativePath: string, node: IProblem, selectedLanguage: string): Promise { let tag: string = ""; if (/\$\{ tag \} /i.test(relativePath)) { tag = (await this.resolveTagForProblem(node)) || ""; @@ -1233,47 +1026,42 @@ class TreeViewController implements Disposable { } 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 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 { + public async resolveTagForProblem(problem: IProblem): Promise { if (problem.tags.length === 1) { return problem.tags[0]; } @@ -1284,9 +1072,7 @@ class TreeViewController implements Disposable { }); } - public async resolveCompanyForProblem( - problem: IProblem - ): Promise { + public async resolveCompanyForProblem(problem: IProblem): Promise { if (problem.companies.length === 1) { return problem.companies[0]; } @@ -1308,12 +1094,8 @@ class TreeViewController implements Disposable { 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的时间 + 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) { @@ -1334,12 +1116,8 @@ class TreeViewController implements Disposable { 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的时间 + 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) { @@ -1368,10 +1146,7 @@ class TreeViewController implements Disposable { 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) - ); + this.explorerNodeMap.set(problem.id, new NodeModel(problem, true, user_score)); for (const company of problem.companies) { this.companySet.add(company); } @@ -1508,10 +1283,7 @@ class TreeViewController implements Disposable { if (!this.canShow(element)) { return; } - if ( - rank_a <= Number(element.score) && - Number(element.score) <= rank_b - ) { + if (rank_a <= Number(element.score) && Number(element.score) <= rank_b) { sorceNode.push(element); } }); @@ -1566,9 +1338,7 @@ class TreeViewController implements Disposable { } public getAllNodes(): NodeModel[] { - return this.applySortingStrategy( - Array.from(this.explorerNodeMap.values()).filter((p) => this.canShow(p)) - ); + return this.applySortingStrategy(Array.from(this.explorerNodeMap.values()).filter((p) => this.canShow(p))); } public getAllDifficultyNodes(): NodeModel[] { @@ -1780,10 +1550,7 @@ class TreeViewController implements Disposable { this.tagSet.clear(); } - private sortSubCategoryNodes( - subCategoryNodes: NodeModel[], - category: Category - ): void { + private sortSubCategoryNodes(subCategoryNodes: NodeModel[], category: Category): void { switch (category) { case Category.Difficulty: subCategoryNodes.sort((a: NodeModel, b: NodeModel): number => { @@ -1823,27 +1590,15 @@ class TreeViewController implements Disposable { const strategy: SortingStrategy = getSortingStrategy(); switch (strategy) { case SortingStrategy.AcceptanceRateAsc: - return nodes.sort( - (x: NodeModel, y: NodeModel) => - Number(x.acceptanceRate) - Number(y.acceptanceRate) - ); + 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) - ); + 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) - ); + 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) - ); + 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) - ); + return nodes.sort((x: NodeModel, y: NodeModel) => Number(y.id) - Number(x.id)); default: return nodes; } diff --git a/src/dao/choiceDao.ts b/src/dao/choiceDao.ts index 5efc4f6..178f2ad 100644 --- a/src/dao/choiceDao.ts +++ b/src/dao/choiceDao.ts @@ -17,315 +17,254 @@ class ChoiceDao { 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, + 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, + 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, + 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, + 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, + 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, + 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, + 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, + 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, + 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, + 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, + 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, - ], + 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, + 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, + 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, + 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, + 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, + 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, - ], + 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, + 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, + 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, + 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, + 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, + 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, ], }, ]; diff --git a/src/dao/tagsDao.ts b/src/dao/tagsDao.ts index 05d00e2..eeca573 100644 --- a/src/dao/tagsDao.ts +++ b/src/dao/tagsDao.ts @@ -32,12 +32,7 @@ class TagsDao { "21": { topicTags: ["recursion", "linked-list"] }, "22": { topicTags: ["string", "dynamic-programming", "backtracking"] }, "23": { - topicTags: [ - "linked-list", - "divide-and-conquer", - "heap-priority-queue", - "merge-sort", - ], + topicTags: ["linked-list", "divide-and-conquer", "heap-priority-queue", "merge-sort"], }, "24": { topicTags: ["recursion", "linked-list"] }, "25": { topicTags: ["recursion", "linked-list"] }, @@ -58,13 +53,7 @@ class TagsDao { "40": { topicTags: ["array", "backtracking"] }, "41": { topicTags: ["array", "hash-table"] }, "42": { - topicTags: [ - "stack", - "array", - "two-pointers", - "dynamic-programming", - "monotonic-stack", - ], + topicTags: ["stack", "array", "two-pointers", "dynamic-programming", "monotonic-stack"], }, "43": { topicTags: ["math", "string", "simulation"] }, "44": { @@ -111,13 +100,7 @@ class TagsDao { "83": { topicTags: ["linked-list"] }, "84": { topicTags: ["stack", "array", "monotonic-stack"] }, "85": { - topicTags: [ - "stack", - "array", - "dynamic-programming", - "matrix", - "monotonic-stack", - ], + topicTags: ["stack", "array", "dynamic-programming", "matrix", "monotonic-stack"], }, "86": { topicTags: ["linked-list", "two-pointers"] }, "87": { topicTags: ["string", "dynamic-programming"] }, @@ -129,150 +112,61 @@ class TagsDao { "93": { topicTags: ["string", "backtracking"] }, "94": { topicTags: ["stack", "tree", "depth-first-search", "binary-tree"] }, "95": { - topicTags: [ - "tree", - "binary-search-tree", - "dynamic-programming", - "backtracking", - "binary-tree", - ], + topicTags: ["tree", "binary-search-tree", "dynamic-programming", "backtracking", "binary-tree"], }, "96": { - topicTags: [ - "tree", - "binary-search-tree", - "math", - "dynamic-programming", - "binary-tree", - ], + 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", - ], + topicTags: ["tree", "depth-first-search", "binary-search-tree", "binary-tree"], }, "99": { - topicTags: [ - "tree", - "depth-first-search", - "binary-search-tree", - "binary-tree", - ], + topicTags: ["tree", "depth-first-search", "binary-search-tree", "binary-tree"], }, "100": { - topicTags: [ - "tree", - "depth-first-search", - "breadth-first-search", - "binary-tree", - ], + topicTags: ["tree", "depth-first-search", "breadth-first-search", "binary-tree"], }, "101": { - topicTags: [ - "tree", - "depth-first-search", - "breadth-first-search", - "binary-tree", - ], + 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", - ], + topicTags: ["tree", "depth-first-search", "breadth-first-search", "binary-tree"], }, "105": { - topicTags: [ - "tree", - "array", - "hash-table", - "divide-and-conquer", - "binary-tree", - ], + topicTags: ["tree", "array", "hash-table", "divide-and-conquer", "binary-tree"], }, "106": { - topicTags: [ - "tree", - "array", - "hash-table", - "divide-and-conquer", - "binary-tree", - ], + 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", - ], + topicTags: ["tree", "binary-search-tree", "array", "divide-and-conquer", "binary-tree"], }, "109": { - topicTags: [ - "tree", - "binary-search-tree", - "linked-list", - "divide-and-conquer", - "binary-tree", - ], + 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", - ], + topicTags: ["tree", "depth-first-search", "breadth-first-search", "binary-tree"], }, "112": { - topicTags: [ - "tree", - "depth-first-search", - "breadth-first-search", - "binary-tree", - ], + 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", - ], + 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", - ], + 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", - ], + topicTags: ["tree", "depth-first-search", "breadth-first-search", "linked-list", "binary-tree"], }, "118": { topicTags: ["array", "dynamic-programming"] }, "119": { topicTags: ["array", "dynamic-programming"] }, @@ -281,43 +175,22 @@ class TagsDao { "122": { topicTags: ["greedy", "array", "dynamic-programming"] }, "123": { topicTags: ["array", "dynamic-programming"] }, "124": { - topicTags: [ - "tree", - "depth-first-search", - "dynamic-programming", - "binary-tree", - ], + topicTags: ["tree", "depth-first-search", "dynamic-programming", "binary-tree"], }, "125": { topicTags: ["two-pointers", "string"] }, "126": { - topicTags: [ - "breadth-first-search", - "hash-table", - "string", - "backtracking", - ], + 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", - ], + 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", - ], + topicTags: ["depth-first-search", "breadth-first-search", "graph", "hash-table"], }, "134": { topicTags: ["greedy", "array"] }, "135": { topicTags: ["greedy", "array"] }, @@ -325,23 +198,10 @@ class TagsDao { "137": { topicTags: ["bit-manipulation", "array"] }, "138": { topicTags: ["hash-table", "linked-list"] }, "139": { - topicTags: [ - "trie", - "memoization", - "hash-table", - "string", - "dynamic-programming", - ], + topicTags: ["trie", "memoization", "hash-table", "string", "dynamic-programming"], }, "140": { - topicTags: [ - "trie", - "memoization", - "hash-table", - "string", - "dynamic-programming", - "backtracking", - ], + 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"] }, @@ -357,13 +217,7 @@ class TagsDao { }, "147": { topicTags: ["linked-list", "sorting"] }, "148": { - topicTags: [ - "linked-list", - "two-pointers", - "divide-and-conquer", - "sorting", - "merge-sort", - ], + topicTags: ["linked-list", "two-pointers", "divide-and-conquer", "sorting", "merge-sort"], }, "149": { topicTags: ["geometry", "array", "hash-table", "math"] }, "150": { topicTags: ["stack", "array", "math"] }, @@ -386,34 +240,15 @@ class TagsDao { "167": { topicTags: ["array", "two-pointers", "binary-search"] }, "168": { topicTags: ["math", "string"] }, "169": { - topicTags: [ - "array", - "hash-table", - "divide-and-conquer", - "counting", - "sorting", - ], + topicTags: ["array", "hash-table", "divide-and-conquer", "counting", "sorting"], }, "170": { - topicTags: [ - "design", - "array", - "hash-table", - "two-pointers", - "data-stream", - ], + 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", - ], + topicTags: ["stack", "tree", "design", "binary-search-tree", "binary-tree", "iterator"], }, "174": { topicTags: ["array", "dynamic-programming", "matrix"] }, "175": { topicTags: ["database"] }, @@ -429,14 +264,7 @@ class TagsDao { "185": { topicTags: ["database"] }, "186": { topicTags: ["two-pointers", "string"] }, "187": { - topicTags: [ - "bit-manipulation", - "hash-table", - "string", - "sliding-window", - "hash-function", - "rolling-hash", - ], + topicTags: ["bit-manipulation", "hash-table", "string", "sliding-window", "hash-function", "rolling-hash"], }, "188": { topicTags: ["array", "dynamic-programming"] }, "189": { topicTags: ["array", "math", "two-pointers"] }, @@ -450,21 +278,10 @@ class TagsDao { "197": { topicTags: ["database"] }, "198": { topicTags: ["array", "dynamic-programming"] }, "199": { - topicTags: [ - "tree", - "depth-first-search", - "breadth-first-search", - "binary-tree", - ], + topicTags: ["tree", "depth-first-search", "breadth-first-search", "binary-tree"], }, "200": { - topicTags: [ - "depth-first-search", - "breadth-first-search", - "union-find", - "array", - "matrix", - ], + topicTags: ["depth-first-search", "breadth-first-search", "union-find", "array", "matrix"], }, "201": { topicTags: ["bit-manipulation"] }, "202": { topicTags: ["hash-table", "math", "two-pointers"] }, @@ -473,24 +290,14 @@ class TagsDao { "205": { topicTags: ["hash-table", "string"] }, "206": { topicTags: ["recursion", "linked-list"] }, "207": { - topicTags: [ - "depth-first-search", - "breadth-first-search", - "graph", - "topological-sort", - ], + 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", - ], + 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"] }, @@ -499,13 +306,7 @@ class TagsDao { topicTags: ["string", "string-matching", "hash-function", "rolling-hash"], }, "215": { - topicTags: [ - "array", - "divide-and-conquer", - "quickselect", - "sorting", - "heap-priority-queue", - ], + topicTags: ["array", "divide-and-conquer", "quickselect", "sorting", "heap-priority-queue"], }, "216": { topicTags: ["array", "backtracking"] }, "217": { topicTags: ["array", "hash-table", "sorting"] }, @@ -522,13 +323,7 @@ class TagsDao { }, "219": { topicTags: ["array", "hash-table", "sliding-window"] }, "220": { - topicTags: [ - "array", - "bucket-sort", - "ordered-set", - "sorting", - "sliding-window", - ], + topicTags: ["array", "bucket-sort", "ordered-set", "sorting", "sliding-window"], }, "221": { topicTags: ["array", "dynamic-programming", "matrix"] }, "222": { @@ -538,59 +333,32 @@ class TagsDao { "224": { topicTags: ["stack", "recursion", "math", "string"] }, "225": { topicTags: ["stack", "design", "queue"] }, "226": { - topicTags: [ - "tree", - "depth-first-search", - "breadth-first-search", - "binary-tree", - ], + 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", - ], + 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", - ], + 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", - ], + 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", - ], + topicTags: ["recursion", "memoization", "math", "string", "dynamic-programming"], }, "242": { topicTags: ["hash-table", "string", "sorting"] }, "243": { topicTags: ["array", "string"] }, @@ -606,88 +374,38 @@ class TagsDao { "251": { topicTags: ["design", "array", "two-pointers", "iterator"] }, "252": { topicTags: ["array", "sorting"] }, "253": { - topicTags: [ - "greedy", - "array", - "two-pointers", - "prefix-sum", - "sorting", - "heap-priority-queue", - ], + 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", - ], + "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", - ], + 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", - ], + 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", - ], + topicTags: ["bit-manipulation", "array", "hash-table", "math", "binary-search", "sorting"], }, "269": { - topicTags: [ - "depth-first-search", - "breadth-first-search", - "graph", - "topological-sort", - "array", - "string", - ], + 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", - ], + topicTags: ["tree", "depth-first-search", "binary-search-tree", "binary-search", "binary-tree"], }, "271": { topicTags: ["design", "array", "string"] }, "272": { @@ -716,12 +434,7 @@ class TagsDao { "283": { topicTags: ["array", "two-pointers"] }, "284": { topicTags: ["design", "array", "iterator"] }, "285": { - topicTags: [ - "tree", - "depth-first-search", - "binary-search-tree", - "binary-tree", - ], + topicTags: ["tree", "depth-first-search", "binary-search-tree", "binary-tree"], }, "286": { topicTags: ["breadth-first-search", "array", "matrix"] }, "287": { @@ -734,46 +447,21 @@ class TagsDao { "292": { topicTags: ["brainteaser", "math", "game-theory"] }, "293": { topicTags: ["string"] }, "294": { - topicTags: [ - "memoization", - "math", - "dynamic-programming", - "backtracking", - "game-theory", - ], + topicTags: ["memoization", "math", "dynamic-programming", "backtracking", "game-theory"], }, "295": { - topicTags: [ - "design", - "two-pointers", - "data-stream", - "sorting", - "heap-priority-queue", - ], + 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", - ], + 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", - ], + topicTags: ["depth-first-search", "breadth-first-search", "array", "binary-search", "matrix"], }, "303": { topicTags: ["design", "array", "prefix-sum"] }, "304": { topicTags: ["design", "array", "matrix", "prefix-sum"] }, @@ -783,34 +471,17 @@ class TagsDao { topicTags: ["design", "binary-indexed-tree", "segment-tree", "array"], }, "308": { - topicTags: [ - "design", - "binary-indexed-tree", - "segment-tree", - "array", - "matrix", - ], + 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", - ], + 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", - ], + topicTags: ["tree", "depth-first-search", "breadth-first-search", "hash-table", "binary-tree"], }, "315": { topicTags: [ @@ -833,12 +504,7 @@ class TagsDao { topicTags: ["breadth-first-search", "array", "dynamic-programming"], }, "323": { - topicTags: [ - "depth-first-search", - "breadth-first-search", - "union-find", - "graph", - ], + topicTags: ["depth-first-search", "breadth-first-search", "union-find", "graph"], }, "324": { topicTags: ["array", "divide-and-conquer", "quickselect", "sorting"], @@ -873,37 +539,19 @@ class TagsDao { "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", - ], + 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", - ], + 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", - ], + topicTags: ["stack", "tree", "depth-first-search", "design", "queue", "iterator"], }, "342": { topicTags: ["bit-manipulation", "recursion", "math"] }, "343": { topicTags: ["math", "dynamic-programming"] }, @@ -924,22 +572,10 @@ class TagsDao { }, "348": { topicTags: ["design", "array", "hash-table", "matrix"] }, "349": { - topicTags: [ - "array", - "hash-table", - "two-pointers", - "binary-search", - "sorting", - ], + topicTags: ["array", "hash-table", "two-pointers", "binary-search", "sorting"], }, "350": { - topicTags: [ - "array", - "hash-table", - "two-pointers", - "binary-search", - "sorting", - ], + topicTags: ["array", "hash-table", "two-pointers", "binary-search", "sorting"], }, "351": { topicTags: ["dynamic-programming", "backtracking"] }, "352": { topicTags: ["design", "binary-search", "ordered-set"] }, @@ -953,14 +589,7 @@ class TagsDao { "356": { topicTags: ["array", "hash-table", "math"] }, "357": { topicTags: ["math", "dynamic-programming", "backtracking"] }, "358": { - topicTags: [ - "greedy", - "hash-table", - "string", - "counting", - "sorting", - "heap-priority-queue", - ], + topicTags: ["greedy", "hash-table", "string", "counting", "sorting", "heap-priority-queue"], }, "359": { topicTags: ["design", "hash-table"] }, "360": { topicTags: ["array", "math", "two-pointers", "sorting"] }, @@ -969,13 +598,7 @@ class TagsDao { topicTags: ["design", "queue", "array", "hash-table", "binary-search"], }, "363": { - topicTags: [ - "array", - "binary-search", - "matrix", - "ordered-set", - "prefix-sum", - ], + topicTags: ["array", "binary-search", "matrix", "ordered-set", "prefix-sum"], }, "364": { topicTags: ["stack", "depth-first-search", "breadth-first-search"], @@ -996,13 +619,7 @@ class TagsDao { "376": { topicTags: ["greedy", "array", "dynamic-programming"] }, "377": { topicTags: ["array", "dynamic-programming"] }, "378": { - topicTags: [ - "array", - "binary-search", - "matrix", - "sorting", - "heap-priority-queue", - ], + topicTags: ["array", "binary-search", "matrix", "sorting", "heap-priority-queue"], }, "379": { topicTags: ["design", "queue", "array", "hash-table", "linked-list"], @@ -1031,64 +648,31 @@ class TagsDao { "393": { topicTags: ["bit-manipulation", "array"] }, "394": { topicTags: ["stack", "recursion", "string"] }, "395": { - topicTags: [ - "hash-table", - "string", - "divide-and-conquer", - "sliding-window", - ], + topicTags: ["hash-table", "string", "divide-and-conquer", "sliding-window"], }, "396": { topicTags: ["array", "math", "dynamic-programming"] }, "397": { - topicTags: [ - "greedy", - "bit-manipulation", - "memoization", - "dynamic-programming", - ], + 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", - ], + 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", - ], + 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", - ], + topicTags: ["greedy", "binary-indexed-tree", "segment-tree", "array", "sorting"], }, "407": { - topicTags: [ - "breadth-first-search", - "array", - "matrix", - "heap-priority-queue", - ], + topicTags: ["breadth-first-search", "array", "matrix", "heap-priority-queue"], }, "408": { topicTags: ["two-pointers", "string"] }, "409": { topicTags: ["greedy", "hash-table", "string"] }, @@ -1102,12 +686,7 @@ class TagsDao { "415": { topicTags: ["math", "string", "simulation"] }, "416": { topicTags: ["array", "dynamic-programming"] }, "417": { - topicTags: [ - "depth-first-search", - "breadth-first-search", - "array", - "matrix", - ], + topicTags: ["depth-first-search", "breadth-first-search", "array", "matrix"], }, "418": { topicTags: ["string", "dynamic-programming", "simulation"] }, "419": { topicTags: ["depth-first-search", "array", "matrix"] }, @@ -1130,25 +709,14 @@ class TagsDao { }, "427": { topicTags: ["tree", "array", "divide-and-conquer", "matrix"] }, "428": { - topicTags: [ - "tree", - "depth-first-search", - "breadth-first-search", - "string", - ], + 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", - ], + topicTags: ["tree", "depth-first-search", "breadth-first-search", "design", "binary-tree"], }, "432": { topicTags: ["design", "hash-table", "linked-list", "doubly-linked-list"], @@ -1182,27 +750,14 @@ class TagsDao { }, "450": { topicTags: ["tree", "binary-search-tree", "binary-tree"] }, "451": { - topicTags: [ - "hash-table", - "string", - "bucket-sort", - "counting", - "sorting", - "heap-priority-queue", - ], + 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", - ], + topicTags: ["stack", "array", "binary-search", "ordered-set", "monotonic-stack"], }, "457": { topicTags: ["array", "hash-table", "two-pointers"] }, "458": { topicTags: ["math", "dynamic-programming", "combinatorics"] }, @@ -1213,62 +768,27 @@ class TagsDao { "461": { topicTags: ["bit-manipulation"] }, "462": { topicTags: ["array", "math", "sorting"] }, "463": { - topicTags: [ - "depth-first-search", - "breadth-first-search", - "array", - "matrix", - ], + topicTags: ["depth-first-search", "breadth-first-search", "array", "matrix"], }, "464": { - topicTags: [ - "bit-manipulation", - "memoization", - "math", - "dynamic-programming", - "bitmask", - "game-theory", - ], + topicTags: ["bit-manipulation", "memoization", "math", "dynamic-programming", "bitmask", "game-theory"], }, "465": { - topicTags: [ - "bit-manipulation", - "array", - "dynamic-programming", - "backtracking", - "bitmask", - ], + 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", - ], + topicTags: ["math", "rejection-sampling", "probability-and-statistics", "randomized"], }, - "471": { topicTags: ["string", "dynamic-programming"] }, - "472": { - topicTags: [ - "depth-first-search", - "trie", - "array", - "string", - "dynamic-programming", - ], + "471": { topicTags: ["string", "dynamic-programming"] }, + "472": { + topicTags: ["depth-first-search", "trie", "array", "string", "dynamic-programming"], }, "473": { - topicTags: [ - "bit-manipulation", - "array", - "dynamic-programming", - "backtracking", - "bitmask", - ], + topicTags: ["bit-manipulation", "array", "dynamic-programming", "backtracking", "bitmask"], }, "474": { topicTags: ["array", "string", "dynamic-programming"] }, "475": { topicTags: ["array", "two-pointers", "binary-search", "sorting"] }, @@ -1279,12 +799,7 @@ class TagsDao { }, "479": { topicTags: ["math"] }, "480": { - topicTags: [ - "array", - "hash-table", - "sliding-window", - "heap-priority-queue", - ], + topicTags: ["array", "hash-table", "sliding-window", "heap-priority-queue"], }, "481": { topicTags: ["two-pointers", "string"] }, "482": { topicTags: ["string"] }, @@ -1292,22 +807,11 @@ class TagsDao { "484": { topicTags: ["stack", "greedy", "array", "string"] }, "485": { topicTags: ["array"] }, "486": { - topicTags: [ - "recursion", - "array", - "math", - "dynamic-programming", - "game-theory", - ], + topicTags: ["recursion", "array", "math", "dynamic-programming", "game-theory"], }, "487": { topicTags: ["array", "dynamic-programming", "sliding-window"] }, "488": { - topicTags: [ - "breadth-first-search", - "memoization", - "string", - "dynamic-programming", - ], + topicTags: ["breadth-first-search", "memoization", "string", "dynamic-programming"], }, "489": { topicTags: ["backtracking", "interactive"] }, "490": { @@ -1332,45 +836,21 @@ class TagsDao { "495": { topicTags: ["array", "simulation"] }, "496": { topicTags: ["stack", "array", "hash-table", "monotonic-stack"] }, "497": { - topicTags: [ - "reservoir-sampling", - "math", - "binary-search", - "ordered-set", - "prefix-sum", - "randomized", - ], + 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", - ], + 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", - ], + 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", - ], + topicTags: ["depth-first-search", "breadth-first-search", "graph", "shortest-path", "heap-priority-queue"], }, "506": { topicTags: ["array", "sorting", "heap-priority-queue"] }, "507": { topicTags: ["math"] }, @@ -1384,28 +864,13 @@ class TagsDao { "511": { topicTags: ["database"] }, "512": { topicTags: ["database"] }, "513": { - topicTags: [ - "tree", - "depth-first-search", - "breadth-first-search", - "binary-tree", - ], + topicTags: ["tree", "depth-first-search", "breadth-first-search", "binary-tree"], }, "514": { - topicTags: [ - "depth-first-search", - "breadth-first-search", - "string", - "dynamic-programming", - ], + topicTags: ["depth-first-search", "breadth-first-search", "string", "dynamic-programming"], }, "515": { - topicTags: [ - "tree", - "depth-first-search", - "breadth-first-search", - "binary-tree", - ], + topicTags: ["tree", "depth-first-search", "breadth-first-search", "binary-tree"], }, "516": { topicTags: ["string", "dynamic-programming"] }, "517": { topicTags: ["greedy", "array"] }, @@ -1422,42 +887,19 @@ class TagsDao { "524": { topicTags: ["array", "two-pointers", "string", "sorting"] }, "525": { topicTags: ["array", "hash-table", "prefix-sum"] }, "526": { - topicTags: [ - "bit-manipulation", - "array", - "dynamic-programming", - "backtracking", - "bitmask", - ], + 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", - ], + topicTags: ["depth-first-search", "breadth-first-search", "array", "matrix"], }, "530": { - topicTags: [ - "tree", - "depth-first-search", - "breadth-first-search", - "binary-search-tree", - "binary-tree", - ], + 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", - ], + topicTags: ["array", "hash-table", "two-pointers", "binary-search", "sorting"], }, "533": { topicTags: ["array", "hash-table", "matrix"] }, "534": { topicTags: ["database"] }, @@ -1467,35 +909,20 @@ class TagsDao { }, "537": { topicTags: ["math", "string", "simulation"] }, "538": { - topicTags: [ - "tree", - "depth-first-search", - "binary-search-tree", - "binary-tree", - ], + 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", - ], + 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", - ], + topicTags: ["depth-first-search", "breadth-first-search", "union-find", "graph"], }, "548": { topicTags: ["array", "prefix-sum"] }, "549": { topicTags: ["tree", "depth-first-search", "binary-tree"] }, @@ -1526,13 +953,7 @@ class TagsDao { "570": { topicTags: ["database"] }, "571": { topicTags: ["database"] }, "572": { - topicTags: [ - "tree", - "depth-first-search", - "binary-tree", - "string-matching", - "hash-function", - ], + topicTags: ["tree", "depth-first-search", "binary-tree", "string-matching", "hash-function"], }, "573": { topicTags: ["array", "math"] }, "574": { topicTags: ["database"] }, @@ -1543,23 +964,10 @@ class TagsDao { "579": { topicTags: ["database"] }, "580": { topicTags: ["database"] }, "581": { - topicTags: [ - "stack", - "greedy", - "array", - "two-pointers", - "sorting", - "monotonic-stack", - ], + topicTags: ["stack", "greedy", "array", "two-pointers", "sorting", "monotonic-stack"], }, "582": { - topicTags: [ - "tree", - "depth-first-search", - "breadth-first-search", - "array", - "hash-table", - ], + topicTags: ["tree", "depth-first-search", "breadth-first-search", "array", "hash-table"], }, "583": { topicTags: ["string", "dynamic-programming"] }, "584": { topicTags: ["database"] }, @@ -1594,13 +1002,7 @@ class TagsDao { "609": { topicTags: ["array", "hash-table", "string"] }, "610": { topicTags: ["database"] }, "611": { - topicTags: [ - "greedy", - "array", - "two-pointers", - "binary-search", - "sorting", - ], + topicTags: ["greedy", "array", "two-pointers", "binary-search", "sorting"], }, "612": { topicTags: ["database"] }, "613": { topicTags: ["database"] }, @@ -1610,34 +1012,17 @@ class TagsDao { topicTags: ["trie", "array", "hash-table", "string", "string-matching"], }, "617": { - topicTags: [ - "tree", - "depth-first-search", - "breadth-first-search", - "binary-tree", - ], + 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", - ], + 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", - ], + topicTags: ["tree", "depth-first-search", "breadth-first-search", "binary-tree"], }, "624": { topicTags: ["greedy", "array"] }, "625": { topicTags: ["greedy", "math"] }, @@ -1648,36 +1033,17 @@ class TagsDao { "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", - ], + 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", - ], + topicTags: ["tree", "depth-first-search", "breadth-first-search", "binary-tree"], }, "638": { - topicTags: [ - "bit-manipulation", - "memoization", - "array", - "dynamic-programming", - "backtracking", - "bitmask", - ], + topicTags: ["bit-manipulation", "memoization", "array", "dynamic-programming", "backtracking", "bitmask"], }, "639": { topicTags: ["string", "dynamic-programming"] }, "640": { topicTags: ["math", "string", "simulation"] }, @@ -1709,33 +1075,15 @@ class TagsDao { ], }, "654": { - topicTags: [ - "stack", - "tree", - "array", - "divide-and-conquer", - "binary-tree", - "monotonic-stack", - ], + topicTags: ["stack", "tree", "array", "divide-and-conquer", "binary-tree", "monotonic-stack"], }, "655": { - topicTags: [ - "tree", - "depth-first-search", - "breadth-first-search", - "binary-tree", - ], + 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", - ], + topicTags: ["array", "two-pointers", "binary-search", "sorting", "heap-priority-queue"], }, "659": { topicTags: ["greedy", "array", "hash-table", "heap-priority-queue"], @@ -1743,12 +1091,7 @@ class TagsDao { "660": { topicTags: ["math"] }, "661": { topicTags: ["array", "matrix"] }, "662": { - topicTags: [ - "tree", - "depth-first-search", - "breadth-first-search", - "binary-tree", - ], + topicTags: ["tree", "depth-first-search", "breadth-first-search", "binary-tree"], }, "663": { topicTags: ["tree", "depth-first-search", "binary-tree"] }, "664": { topicTags: ["string", "dynamic-programming"] }, @@ -1759,39 +1102,19 @@ class TagsDao { "667": { topicTags: ["array", "math"] }, "668": { topicTags: ["math", "binary-search"] }, "669": { - topicTags: [ - "tree", - "depth-first-search", - "binary-search-tree", - "binary-tree", - ], + 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", - ], + topicTags: ["bit-manipulation", "depth-first-search", "breadth-first-search", "math"], }, "673": { - topicTags: [ - "binary-indexed-tree", - "segment-tree", - "array", - "dynamic-programming", - ], + topicTags: ["binary-indexed-tree", "segment-tree", "array", "dynamic-programming"], }, "674": { topicTags: ["array"] }, "675": { - topicTags: [ - "breadth-first-search", - "array", - "matrix", - "heap-priority-queue", - ], + topicTags: ["breadth-first-search", "array", "matrix", "heap-priority-queue"], }, "676": { topicTags: ["design", "trie", "hash-table", "string"] }, "677": { topicTags: ["design", "trie", "hash-table", "string"] }, @@ -1801,28 +1124,13 @@ class TagsDao { "681": { topicTags: ["string", "enumeration"] }, "682": { topicTags: ["stack", "array", "simulation"] }, "683": { - topicTags: [ - "binary-indexed-tree", - "array", - "ordered-set", - "sliding-window", - ], + topicTags: ["binary-indexed-tree", "array", "ordered-set", "sliding-window"], }, "684": { - topicTags: [ - "depth-first-search", - "breadth-first-search", - "union-find", - "graph", - ], + topicTags: ["depth-first-search", "breadth-first-search", "union-find", "graph"], }, "685": { - topicTags: [ - "depth-first-search", - "breadth-first-search", - "union-find", - "graph", - ], + topicTags: ["depth-first-search", "breadth-first-search", "union-find", "graph"], }, "686": { topicTags: ["string", "string-matching"] }, "687": { topicTags: ["tree", "depth-first-search", "binary-tree"] }, @@ -1832,145 +1140,61 @@ class TagsDao { topicTags: ["depth-first-search", "breadth-first-search", "hash-table"], }, "691": { - topicTags: [ - "bit-manipulation", - "array", - "string", - "dynamic-programming", - "backtracking", - "bitmask", - ], + topicTags: ["bit-manipulation", "array", "string", "dynamic-programming", "backtracking", "bitmask"], }, "692": { - topicTags: [ - "trie", - "hash-table", - "string", - "bucket-sort", - "counting", - "sorting", - "heap-priority-queue", - ], + 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", - ], + 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", - ], + 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", - ], + 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", - ], + 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", - ], + topicTags: ["design", "array", "hash-table", "linked-list", "hash-function"], }, "706": { - topicTags: [ - "design", - "array", - "hash-table", - "linked-list", - "hash-function", - ], + 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", - ], + topicTags: ["hash-table", "math", "binary-search", "sorting", "randomized"], }, "711": { - topicTags: [ - "depth-first-search", - "breadth-first-search", - "union-find", - "hash-table", - "hash-function", - ], + 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", - ], + 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", - ], + 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", - ], + topicTags: ["depth-first-search", "breadth-first-search", "union-find", "array", "string"], }, "722": { topicTags: ["array", "string"] }, "723": { topicTags: ["array", "two-pointers", "matrix", "simulation"] }, @@ -1990,46 +1214,23 @@ class TagsDao { topicTags: ["design", "segment-tree", "binary-search", "ordered-set"], }, "733": { - topicTags: [ - "depth-first-search", - "breadth-first-search", - "array", - "matrix", - ], + 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", - ], + 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", - ], + topicTags: ["tree", "depth-first-search", "breadth-first-search", "binary-tree"], }, "743": { - topicTags: [ - "depth-first-search", - "breadth-first-search", - "graph", - "shortest-path", - "heap-priority-queue", - ], + 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"] }, @@ -2037,13 +1238,7 @@ class TagsDao { "747": { topicTags: ["array", "sorting"] }, "748": { topicTags: ["array", "hash-table", "string"] }, "749": { - topicTags: [ - "depth-first-search", - "breadth-first-search", - "array", - "matrix", - "simulation", - ], + topicTags: ["depth-first-search", "breadth-first-search", "array", "matrix", "simulation"], }, "750": { topicTags: ["array", "math", "dynamic-programming", "matrix"] }, "751": { topicTags: ["bit-manipulation", "string"] }, @@ -2054,11 +1249,7 @@ class TagsDao { "754": { topicTags: ["math", "binary-search"] }, "755": { topicTags: ["array", "simulation"] }, "756": { - topicTags: [ - "bit-manipulation", - "depth-first-search", - "breadth-first-search", - ], + topicTags: ["bit-manipulation", "depth-first-search", "breadth-first-search"], }, "757": { topicTags: ["greedy", "array", "sorting"] }, "758": { @@ -2071,24 +1262,11 @@ class TagsDao { "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", - ], + 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", - ], + topicTags: ["greedy", "hash-table", "string", "counting", "sorting", "heap-priority-queue"], }, "768": { topicTags: ["stack", "greedy", "array", "sorting", "monotonic-stack"], @@ -2124,22 +1302,11 @@ class TagsDao { "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", - ], + 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", - ], + topicTags: ["depth-first-search", "breadth-first-search", "union-find", "graph"], }, "786": { topicTags: ["array", "binary-search", "sorting", "heap-priority-queue"], @@ -2164,35 +1331,19 @@ class TagsDao { "795": { topicTags: ["array", "two-pointers"] }, "796": { topicTags: ["string", "string-matching"] }, "797": { - topicTags: [ - "depth-first-search", - "breadth-first-search", - "graph", - "backtracking", - ], + 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", - ], + 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", - ], + topicTags: ["bit-manipulation", "array", "math", "dynamic-programming", "bitmask"], }, "806": { topicTags: ["array", "string"] }, "807": { topicTags: ["greedy", "array", "matrix"] }, @@ -2201,13 +1352,7 @@ class TagsDao { }, "809": { topicTags: ["array", "two-pointers", "string"] }, "810": { - topicTags: [ - "bit-manipulation", - "brainteaser", - "array", - "math", - "game-theory", - ], + topicTags: ["bit-manipulation", "brainteaser", "array", "math", "game-theory"], }, "811": { topicTags: ["array", "hash-table", "string", "counting"] }, "812": { topicTags: ["geometry", "array", "math"] }, @@ -2225,22 +1370,10 @@ class TagsDao { "824": { topicTags: ["string"] }, "825": { topicTags: ["array", "two-pointers", "binary-search", "sorting"] }, "826": { - topicTags: [ - "greedy", - "array", - "two-pointers", - "binary-search", - "sorting", - ], + topicTags: ["greedy", "array", "two-pointers", "binary-search", "sorting"], }, "827": { - topicTags: [ - "depth-first-search", - "breadth-first-search", - "union-find", - "array", - "matrix", - ], + topicTags: ["depth-first-search", "breadth-first-search", "union-find", "array", "matrix"], }, "828": { topicTags: ["hash-table", "string", "dynamic-programming"] }, "829": { topicTags: ["math", "enumeration"] }, @@ -2254,22 +1387,11 @@ class TagsDao { "835": { topicTags: ["array", "matrix"] }, "836": { topicTags: ["geometry", "math"] }, "837": { - topicTags: [ - "math", - "dynamic-programming", - "sliding-window", - "probability-and-statistics", - ], + 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", - ], + topicTags: ["depth-first-search", "breadth-first-search", "union-find", "array", "string"], }, "840": { topicTags: ["array", "math", "matrix"] }, "841": { @@ -2281,22 +1403,11 @@ class TagsDao { }, "844": { topicTags: ["stack", "two-pointers", "string", "simulation"] }, "845": { - topicTags: [ - "array", - "two-pointers", - "dynamic-programming", - "enumeration", - ], + 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", - ], + topicTags: ["bit-manipulation", "breadth-first-search", "graph", "dynamic-programming", "bitmask"], }, "848": { topicTags: ["array", "string"] }, "849": { topicTags: ["array"] }, @@ -2328,22 +1439,11 @@ class TagsDao { ], }, "863": { - topicTags: [ - "tree", - "depth-first-search", - "breadth-first-search", - "binary-tree", - ], + 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", - ], + topicTags: ["tree", "depth-first-search", "breadth-first-search", "hash-table", "binary-tree"], }, "866": { topicTags: ["math"] }, "867": { topicTags: ["array", "matrix", "simulation"] }, @@ -2351,12 +1451,7 @@ class TagsDao { "869": { topicTags: ["math", "counting", "enumeration", "sorting"] }, "870": { topicTags: ["greedy", "array", "two-pointers", "sorting"] }, "871": { - topicTags: [ - "greedy", - "array", - "dynamic-programming", - "heap-priority-queue", - ], + topicTags: ["greedy", "array", "dynamic-programming", "heap-priority-queue"], }, "872": { topicTags: ["tree", "depth-first-search", "binary-tree"] }, "873": { topicTags: ["array", "hash-table", "dynamic-programming"] }, @@ -2375,60 +1470,31 @@ class TagsDao { "884": { topicTags: ["hash-table", "string"] }, "885": { topicTags: ["array", "matrix", "simulation"] }, "886": { - topicTags: [ - "depth-first-search", - "breadth-first-search", - "union-find", - "graph", - ], + 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", - ], + 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", - ], + "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", - ], + topicTags: ["array", "math", "string", "binary-search", "dynamic-programming"], }, "903": { topicTags: ["dynamic-programming"] }, "904": { topicTags: ["array", "hash-table", "sliding-window"] }, @@ -2454,14 +1520,7 @@ class TagsDao { ], }, "913": { - topicTags: [ - "graph", - "topological-sort", - "memoization", - "math", - "dynamic-programming", - "game-theory", - ], + topicTags: ["graph", "topological-sort", "memoization", "math", "dynamic-programming", "game-theory"], }, "914": { topicTags: ["array", "hash-table", "math", "counting", "number-theory"], @@ -2470,13 +1529,7 @@ class TagsDao { "916": { topicTags: ["array", "hash-table", "string"] }, "917": { topicTags: ["two-pointers", "string"] }, "918": { - topicTags: [ - "queue", - "array", - "divide-and-conquer", - "dynamic-programming", - "monotonic-queue", - ], + topicTags: ["queue", "array", "divide-and-conquer", "dynamic-programming", "monotonic-queue"], }, "919": { topicTags: ["tree", "breadth-first-search", "design", "binary-tree"], @@ -2488,25 +1541,13 @@ class TagsDao { topicTags: ["array", "hash-table", "two-pointers", "counting", "sorting"], }, "924": { - topicTags: [ - "depth-first-search", - "breadth-first-search", - "union-find", - "array", - "matrix", - ], + 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", - ], + topicTags: ["depth-first-search", "breadth-first-search", "union-find", "array", "matrix"], }, "929": { topicTags: ["array", "hash-table", "string"] }, "930": { @@ -2516,23 +1557,13 @@ class TagsDao { "932": { topicTags: ["array", "math", "divide-and-conquer"] }, "933": { topicTags: ["design", "queue", "data-stream"] }, "934": { - topicTags: [ - "depth-first-search", - "breadth-first-search", - "array", - "matrix", - ], + 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", - ], + topicTags: ["tree", "depth-first-search", "binary-search-tree", "binary-tree"], }, "939": { topicTags: ["geometry", "array", "hash-table", "math", "sorting"], @@ -2541,13 +1572,7 @@ class TagsDao { "941": { topicTags: ["array"] }, "942": { topicTags: ["greedy", "array", "two-pointers", "string"] }, "943": { - topicTags: [ - "bit-manipulation", - "array", - "string", - "dynamic-programming", - "bitmask", - ], + topicTags: ["bit-manipulation", "array", "string", "dynamic-programming", "bitmask"], }, "944": { topicTags: ["array", "string"] }, "945": { topicTags: ["greedy", "array", "counting", "sorting"] }, @@ -2565,12 +1590,7 @@ class TagsDao { "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", - ], + topicTags: ["depth-first-search", "breadth-first-search", "union-find", "graph"], }, "960": { topicTags: ["array", "string", "dynamic-programming"] }, "961": { topicTags: ["array", "hash-table"] }, @@ -2578,47 +1598,23 @@ class TagsDao { "963": { topicTags: ["geometry", "array", "math"] }, "964": { topicTags: ["math", "dynamic-programming"] }, "965": { - topicTags: [ - "tree", - "depth-first-search", - "breadth-first-search", - "binary-tree", - ], + 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", - ], + 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", - ], + 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", - ], + topicTags: ["stack", "array", "dynamic-programming", "ordered-set", "monotonic-stack"], }, "976": { topicTags: ["greedy", "array", "math", "sorting"] }, "977": { topicTags: ["array", "two-pointers", "sorting"] }, @@ -2634,13 +1630,7 @@ class TagsDao { "985": { topicTags: ["array", "simulation"] }, "986": { topicTags: ["array", "two-pointers"] }, "987": { - topicTags: [ - "tree", - "depth-first-search", - "breadth-first-search", - "hash-table", - "binary-tree", - ], + topicTags: ["tree", "depth-first-search", "breadth-first-search", "hash-table", "binary-tree"], }, "988": { topicTags: ["tree", "depth-first-search", "string", "binary-tree"], @@ -2650,32 +1640,14 @@ class TagsDao { "991": { topicTags: ["greedy", "math"] }, "992": { topicTags: ["array", "hash-table", "counting", "sliding-window"] }, "993": { - topicTags: [ - "tree", - "depth-first-search", - "breadth-first-search", - "binary-tree", - ], + 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", - ], + topicTags: ["bit-manipulation", "queue", "array", "prefix-sum", "sliding-window"], }, "996": { - topicTags: [ - "bit-manipulation", - "array", - "math", - "dynamic-programming", - "backtracking", - "bitmask", - ], + topicTags: ["bit-manipulation", "array", "math", "dynamic-programming", "backtracking", "bitmask"], }, "997": { topicTags: ["graph", "array", "hash-table"] }, "998": { topicTags: ["tree", "binary-tree"] }, @@ -2691,14 +1663,7 @@ class TagsDao { "1006": { topicTags: ["stack", "math", "simulation"] }, "1007": { topicTags: ["greedy", "array"] }, "1008": { - topicTags: [ - "stack", - "tree", - "binary-search-tree", - "array", - "binary-tree", - "monotonic-stack", - ], + topicTags: ["stack", "tree", "binary-search-tree", "array", "binary-tree", "monotonic-stack"], }, "1009": { topicTags: ["bit-manipulation"] }, "1010": { topicTags: ["array", "hash-table", "counting"] }, @@ -2712,13 +1677,7 @@ class TagsDao { "1018": { topicTags: ["array"] }, "1019": { topicTags: ["stack", "array", "linked-list", "monotonic-stack"] }, "1020": { - topicTags: [ - "depth-first-search", - "breadth-first-search", - "union-find", - "array", - "matrix", - ], + topicTags: ["depth-first-search", "breadth-first-search", "union-find", "array", "matrix"], }, "1021": { topicTags: ["stack", "string"] }, "1022": { topicTags: ["tree", "depth-first-search", "binary-tree"] }, @@ -2731,12 +1690,7 @@ class TagsDao { }, "1026": { topicTags: ["tree", "depth-first-search", "binary-tree"] }, "1027": { - topicTags: [ - "array", - "hash-table", - "binary-search", - "dynamic-programming", - ], + topicTags: ["array", "hash-table", "binary-search", "dynamic-programming"], }, "1028": { topicTags: ["tree", "depth-first-search", "string", "binary-tree"], @@ -2747,30 +1701,15 @@ class TagsDao { "1032": { topicTags: ["design", "trie", "array", "string", "data-stream"] }, "1033": { topicTags: ["brainteaser", "math"] }, "1034": { - topicTags: [ - "depth-first-search", - "breadth-first-search", - "array", - "matrix", - ], + 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", - ], + 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", - ], + topicTags: ["tree", "depth-first-search", "binary-search-tree", "binary-tree"], }, "1039": { topicTags: ["array", "dynamic-programming"] }, "1040": { topicTags: ["array", "math", "two-pointers", "sorting"] }, @@ -2780,26 +1719,13 @@ class TagsDao { }, "1043": { topicTags: ["array", "dynamic-programming"] }, "1044": { - topicTags: [ - "string", - "binary-search", - "suffix-array", - "sliding-window", - "hash-function", - "rolling-hash", - ], + 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", - ], + topicTags: ["array", "hash-table", "two-pointers", "string", "dynamic-programming"], }, "1049": { topicTags: ["array", "dynamic-programming"] }, "1050": { topicTags: ["database"] }, @@ -2807,14 +1733,7 @@ class TagsDao { "1052": { topicTags: ["array", "sliding-window"] }, "1053": { topicTags: ["greedy", "array"] }, "1054": { - topicTags: [ - "greedy", - "array", - "hash-table", - "counting", - "sorting", - "heap-priority-queue", - ], + topicTags: ["greedy", "array", "hash-table", "counting", "sorting", "heap-priority-queue"], }, "1055": { topicTags: ["greedy", "string", "dynamic-programming"] }, "1056": { topicTags: ["math"] }, @@ -2824,26 +1743,13 @@ class TagsDao { "1060": { topicTags: ["array", "binary-search"] }, "1061": { topicTags: ["union-find", "string"] }, "1062": { - topicTags: [ - "string", - "binary-search", - "dynamic-programming", - "suffix-array", - "hash-function", - "rolling-hash", - ], + 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", - ], + topicTags: ["bit-manipulation", "array", "dynamic-programming", "backtracking", "bitmask"], }, "1067": { topicTags: ["math", "dynamic-programming"] }, "1068": { topicTags: ["database"] }, @@ -2877,13 +1783,7 @@ class TagsDao { topicTags: ["math", "two-pointers", "probability-and-statistics"], }, "1094": { - topicTags: [ - "array", - "prefix-sum", - "sorting", - "simulation", - "heap-priority-queue", - ], + topicTags: ["array", "prefix-sum", "sorting", "simulation", "heap-priority-queue"], }, "1095": { topicTags: ["array", "binary-search", "interactive"] }, "1096": { @@ -2897,14 +1797,7 @@ class TagsDao { "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", - ], + topicTags: ["depth-first-search", "breadth-first-search", "union-find", "array", "matrix", "heap-priority-queue"], }, "1103": { topicTags: ["math", "simulation"] }, "1104": { topicTags: ["tree", "math", "binary-tree"] }, @@ -2927,30 +1820,13 @@ class TagsDao { "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", - ], + topicTags: ["tree", "depth-first-search", "breadth-first-search", "hash-table", "binary-tree"], }, "1124": { - topicTags: [ - "stack", - "array", - "hash-table", - "prefix-sum", - "monotonic-stack", - ], + topicTags: ["stack", "array", "hash-table", "prefix-sum", "monotonic-stack"], }, "1125": { - topicTags: [ - "bit-manipulation", - "array", - "dynamic-programming", - "bitmask", - ], + topicTags: ["bit-manipulation", "array", "dynamic-programming", "bitmask"], }, "1126": { topicTags: ["database"] }, "1127": { topicTags: ["database"] }, @@ -2964,12 +1840,7 @@ class TagsDao { "1133": { topicTags: ["array", "hash-table", "sorting"] }, "1134": { topicTags: ["math"] }, "1135": { - topicTags: [ - "union-find", - "graph", - "minimum-spanning-tree", - "heap-priority-queue", - ], + topicTags: ["union-find", "graph", "minimum-spanning-tree", "heap-priority-queue"], }, "1136": { topicTags: ["graph", "topological-sort"] }, "1137": { topicTags: ["memoization", "math", "dynamic-programming"] }, @@ -2985,14 +1856,7 @@ class TagsDao { "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", - ], + topicTags: ["greedy", "two-pointers", "string", "dynamic-programming", "hash-function", "rolling-hash"], }, "1148": { topicTags: ["database"] }, "1149": { topicTags: ["database"] }, @@ -3004,32 +1868,16 @@ class TagsDao { "1155": { topicTags: ["dynamic-programming"] }, "1156": { topicTags: ["string", "sliding-window"] }, "1157": { - topicTags: [ - "design", - "binary-indexed-tree", - "segment-tree", - "array", - "binary-search", - ], + 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", - ], + "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"] }, @@ -3083,21 +1931,10 @@ class TagsDao { "1200": { topicTags: ["array", "sorting"] }, "1201": { topicTags: ["math", "binary-search", "number-theory"] }, "1202": { - topicTags: [ - "depth-first-search", - "breadth-first-search", - "union-find", - "hash-table", - "string", - ], + topicTags: ["depth-first-search", "breadth-first-search", "union-find", "hash-table", "string"], }, "1203": { - topicTags: [ - "depth-first-search", - "breadth-first-search", - "graph", - "topological-sort", - ], + topicTags: ["depth-first-search", "breadth-first-search", "graph", "topological-sort"], }, "1204": { topicTags: ["database"] }, "1205": { topicTags: ["database"] }, @@ -3135,12 +1972,7 @@ class TagsDao { "1225": { topicTags: ["database"] }, "1226": { topicTags: ["concurrency"] }, "1227": { - topicTags: [ - "brainteaser", - "math", - "dynamic-programming", - "probability-and-statistics", - ], + topicTags: ["brainteaser", "math", "dynamic-programming", "probability-and-statistics"], }, "1228": { topicTags: ["array", "math"] }, "1229": { topicTags: ["array", "two-pointers", "sorting"] }, @@ -3155,12 +1987,7 @@ class TagsDao { topicTags: ["array", "binary-search", "dynamic-programming", "sorting"], }, "1236": { - topicTags: [ - "depth-first-search", - "breadth-first-search", - "string", - "interactive", - ], + topicTags: ["depth-first-search", "breadth-first-search", "string", "interactive"], }, "1237": { topicTags: ["math", "two-pointers", "binary-search", "interactive"], @@ -3177,13 +2004,7 @@ class TagsDao { "1243": { topicTags: ["array", "simulation"] }, "1244": { topicTags: ["design", "hash-table", "sorting"] }, "1245": { - topicTags: [ - "tree", - "depth-first-search", - "breadth-first-search", - "graph", - "topological-sort", - ], + topicTags: ["tree", "depth-first-search", "breadth-first-search", "graph", "topological-sort"], }, "1246": { topicTags: ["array", "dynamic-programming"] }, "1247": { topicTags: ["greedy", "math", "string"] }, @@ -3194,64 +2015,26 @@ class TagsDao { "1252": { topicTags: ["array", "math", "simulation"] }, "1253": { topicTags: ["greedy", "array", "matrix"] }, "1254": { - topicTags: [ - "depth-first-search", - "breadth-first-search", - "union-find", - "array", - "matrix", - ], + topicTags: ["depth-first-search", "breadth-first-search", "union-find", "array", "matrix"], }, "1255": { - topicTags: [ - "bit-manipulation", - "array", - "string", - "dynamic-programming", - "backtracking", - "bitmask", - ], + 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", - ], + topicTags: ["tree", "depth-first-search", "breadth-first-search", "array", "hash-table", "string"], }, "1258": { - topicTags: [ - "union-find", - "array", - "hash-table", - "string", - "backtracking", - ], + 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", - ], + 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", - ], + topicTags: ["breadth-first-search", "array", "matrix", "heap-priority-queue"], }, "1264": { topicTags: ["database"] }, "1265": { @@ -3259,14 +2042,7 @@ class TagsDao { }, "1266": { topicTags: ["geometry", "array", "math"] }, "1267": { - topicTags: [ - "depth-first-search", - "breadth-first-search", - "union-find", - "array", - "counting", - "matrix", - ], + topicTags: ["depth-first-search", "breadth-first-search", "union-find", "array", "counting", "matrix"], }, "1268": { topicTags: ["trie", "array", "string"] }, "1269": { topicTags: ["dynamic-programming"] }, @@ -3287,12 +2063,7 @@ class TagsDao { "1282": { topicTags: ["array", "hash-table"] }, "1283": { topicTags: ["array", "binary-search"] }, "1284": { - topicTags: [ - "bit-manipulation", - "breadth-first-search", - "array", - "matrix", - ], + topicTags: ["bit-manipulation", "breadth-first-search", "array", "matrix"], }, "1285": { topicTags: ["database"] }, "1286": { topicTags: ["design", "string", "backtracking", "iterator"] }, @@ -3312,23 +2083,12 @@ class TagsDao { "1300": { topicTags: ["array", "binary-search", "sorting"] }, "1301": { topicTags: ["array", "dynamic-programming", "matrix"] }, "1302": { - topicTags: [ - "tree", - "depth-first-search", - "breadth-first-search", - "binary-tree", - ], + 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", - ], + topicTags: ["tree", "depth-first-search", "binary-search-tree", "binary-tree", "sorting"], }, "1306": { topicTags: ["depth-first-search", "breadth-first-search", "array"], @@ -3344,23 +2104,13 @@ class TagsDao { "1313": { topicTags: ["array"] }, "1314": { topicTags: ["array", "matrix", "prefix-sum"] }, "1315": { - topicTags: [ - "tree", - "depth-first-search", - "breadth-first-search", - "binary-tree", - ], + 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", - ], + topicTags: ["depth-first-search", "breadth-first-search", "union-find", "graph"], }, "1320": { topicTags: ["string", "dynamic-programming"] }, "1321": { topicTags: ["database"] }, @@ -3380,22 +2130,10 @@ class TagsDao { "1335": { topicTags: ["array", "dynamic-programming"] }, "1336": { topicTags: ["database"] }, "1337": { - topicTags: [ - "array", - "binary-search", - "matrix", - "sorting", - "heap-priority-queue", - ], + topicTags: ["array", "binary-search", "matrix", "sorting", "heap-priority-queue"], }, "1338": { - topicTags: [ - "greedy", - "array", - "hash-table", - "sorting", - "heap-priority-queue", - ], + topicTags: ["greedy", "array", "hash-table", "sorting", "heap-priority-queue"], }, "1339": { topicTags: ["tree", "depth-first-search", "binary-tree"] }, "1340": { topicTags: ["array", "dynamic-programming", "sorting"] }, @@ -3405,32 +2143,14 @@ class TagsDao { "1344": { topicTags: ["math"] }, "1345": { topicTags: ["breadth-first-search", "array", "hash-table"] }, "1346": { - topicTags: [ - "array", - "hash-table", - "two-pointers", - "binary-search", - "sorting", - ], + 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", - ], + topicTags: ["design", "hash-table", "binary-search", "ordered-set", "sorting"], }, "1349": { - topicTags: [ - "bit-manipulation", - "array", - "dynamic-programming", - "bitmask", - "matrix", - ], + topicTags: ["bit-manipulation", "array", "dynamic-programming", "bitmask", "matrix"], }, "1350": { topicTags: ["database"] }, "1351": { topicTags: ["array", "binary-search", "matrix"] }, @@ -3444,14 +2164,7 @@ class TagsDao { "1359": { topicTags: ["math", "dynamic-programming", "combinatorics"] }, "1360": { topicTags: ["math", "string"] }, "1361": { - topicTags: [ - "tree", - "depth-first-search", - "breadth-first-search", - "union-find", - "graph", - "binary-tree", - ], + topicTags: ["tree", "depth-first-search", "breadth-first-search", "union-find", "graph", "binary-tree"], }, "1362": { topicTags: ["math"] }, "1363": { topicTags: ["greedy", "array", "dynamic-programming"] }, @@ -3461,23 +2174,10 @@ class TagsDao { topicTags: ["array", "hash-table", "string", "counting", "sorting"], }, "1367": { - topicTags: [ - "tree", - "depth-first-search", - "breadth-first-search", - "linked-list", - "binary-tree", - ], + 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", - ], + topicTags: ["breadth-first-search", "graph", "array", "matrix", "shortest-path", "heap-priority-queue"], }, "1369": { topicTags: ["database"] }, "1370": { topicTags: ["hash-table", "string", "counting"] }, @@ -3485,21 +2185,10 @@ class TagsDao { topicTags: ["bit-manipulation", "hash-table", "string", "prefix-sum"], }, "1372": { - topicTags: [ - "tree", - "depth-first-search", - "dynamic-programming", - "binary-tree", - ], + topicTags: ["tree", "depth-first-search", "dynamic-programming", "binary-tree"], }, "1373": { - topicTags: [ - "tree", - "depth-first-search", - "binary-search-tree", - "dynamic-programming", - "binary-tree", - ], + topicTags: ["tree", "depth-first-search", "binary-search-tree", "dynamic-programming", "binary-tree"], }, "1374": { topicTags: ["string"] }, "1375": { topicTags: ["array"] }, @@ -3507,33 +2196,16 @@ class TagsDao { topicTags: ["tree", "depth-first-search", "breadth-first-search"], }, "1377": { - topicTags: [ - "tree", - "depth-first-search", - "breadth-first-search", - "graph", - ], + topicTags: ["tree", "depth-first-search", "breadth-first-search", "graph"], }, "1378": { topicTags: ["database"] }, "1379": { - topicTags: [ - "tree", - "depth-first-search", - "breadth-first-search", - "binary-tree", - ], + 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", - ], + topicTags: ["greedy", "tree", "depth-first-search", "binary-search-tree", "divide-and-conquer", "binary-tree"], }, "1383": { topicTags: ["greedy", "array", "sorting", "heap-priority-queue"], @@ -3547,23 +2219,12 @@ class TagsDao { }, "1387": { topicTags: ["memoization", "dynamic-programming", "sorting"] }, "1388": { - topicTags: [ - "greedy", - "array", - "dynamic-programming", - "heap-priority-queue", - ], + 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", - ], + topicTags: ["depth-first-search", "breadth-first-search", "union-find", "array", "matrix"], }, "1392": { topicTags: ["string", "string-matching", "hash-function", "rolling-hash"], @@ -3609,14 +2270,7 @@ class TagsDao { "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", - ], + topicTags: ["queue", "array", "dynamic-programming", "sliding-window", "monotonic-queue", "heap-priority-queue"], }, "1426": { topicTags: ["array", "hash-table"] }, "1427": { topicTags: ["array", "math", "string"] }, @@ -3625,58 +2279,30 @@ class TagsDao { topicTags: ["design", "queue", "array", "hash-table", "data-stream"], }, "1430": { - topicTags: [ - "tree", - "depth-first-search", - "breadth-first-search", - "binary-tree", - ], + 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", - ], + 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", - ], + 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", - ], + 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", - ], + topicTags: ["tree", "depth-first-search", "breadth-first-search", "hash-table"], }, "1444": { topicTags: ["memoization", "array", "dynamic-programming", "matrix"], @@ -3685,12 +2311,7 @@ class TagsDao { "1446": { topicTags: ["string"] }, "1447": { topicTags: ["math", "string", "number-theory"] }, "1448": { - topicTags: [ - "tree", - "depth-first-search", - "breadth-first-search", - "binary-tree", - ], + topicTags: ["tree", "depth-first-search", "breadth-first-search", "binary-tree"], }, "1449": { topicTags: ["array", "dynamic-programming"] }, "1450": { topicTags: ["array"] }, @@ -3701,33 +2322,16 @@ class TagsDao { "1455": { topicTags: ["string", "string-matching"] }, "1456": { topicTags: ["string", "sliding-window"] }, "1457": { - topicTags: [ - "bit-manipulation", - "tree", - "depth-first-search", - "breadth-first-search", - "binary-tree", - ], + 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", - ], + topicTags: ["bit-manipulation", "hash-table", "string", "hash-function", "rolling-hash"], }, "1462": { - topicTags: [ - "depth-first-search", - "breadth-first-search", - "graph", - "topological-sort", - ], + topicTags: ["depth-first-search", "breadth-first-search", "graph", "topological-sort"], }, "1463": { topicTags: ["array", "dynamic-programming", "matrix"] }, "1464": { topicTags: ["array", "sorting", "heap-priority-queue"] }, @@ -3736,47 +2340,23 @@ class TagsDao { topicTags: ["depth-first-search", "breadth-first-search", "graph"], }, "1467": { - topicTags: [ - "math", - "dynamic-programming", - "backtracking", - "combinatorics", - "probability-and-statistics", - ], + topicTags: ["math", "dynamic-programming", "backtracking", "combinatorics", "probability-and-statistics"], }, "1468": { topicTags: ["database"] }, "1469": { - topicTags: [ - "tree", - "depth-first-search", - "breadth-first-search", - "binary-tree", - ], + 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", - ], + 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", - ], + topicTags: ["array", "hash-table", "binary-search", "dynamic-programming", "sliding-window"], }, "1478": { topicTags: ["array", "math", "dynamic-programming", "sorting"] }, "1479": { topicTags: ["database"] }, @@ -3797,52 +2377,24 @@ class TagsDao { }, "1484": { topicTags: ["database"] }, "1485": { - topicTags: [ - "tree", - "depth-first-search", - "breadth-first-search", - "hash-table", - "binary-tree", - ], + 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", - ], + topicTags: ["greedy", "array", "hash-table", "binary-search", "heap-priority-queue"], }, "1489": { - topicTags: [ - "union-find", - "graph", - "minimum-spanning-tree", - "sorting", - "strongly-connected-component", - ], + topicTags: ["union-find", "graph", "minimum-spanning-tree", "sorting", "strongly-connected-component"], }, "1490": { - topicTags: [ - "tree", - "depth-first-search", - "breadth-first-search", - "hash-table", - ], + 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", - ], + topicTags: ["bit-manipulation", "graph", "dynamic-programming", "bitmask"], }, "1495": { topicTags: ["database"] }, "1496": { topicTags: ["hash-table", "string"] }, @@ -3851,13 +2403,7 @@ class TagsDao { topicTags: ["array", "two-pointers", "binary-search", "sorting"], }, "1499": { - topicTags: [ - "queue", - "array", - "sliding-window", - "monotonic-queue", - "heap-priority-queue", - ], + topicTags: ["queue", "array", "sliding-window", "monotonic-queue", "heap-priority-queue"], }, "1500": { topicTags: ["design", "hash-table", "data-stream", "heap-priority-queue"], @@ -3866,24 +2412,13 @@ class TagsDao { "1502": { topicTags: ["array", "sorting"] }, "1503": { topicTags: ["brainteaser", "array", "simulation"] }, "1504": { - topicTags: [ - "stack", - "array", - "dynamic-programming", - "matrix", - "monotonic-stack", - ], + 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", - ], + topicTags: ["bit-manipulation", "tree", "depth-first-search", "hash-table"], }, "1507": { topicTags: ["string"] }, "1508": { @@ -3900,13 +2435,7 @@ class TagsDao { "1517": { topicTags: ["database"] }, "1518": { topicTags: ["math", "simulation"] }, "1519": { - topicTags: [ - "tree", - "depth-first-search", - "breadth-first-search", - "hash-table", - "counting", - ], + topicTags: ["tree", "depth-first-search", "breadth-first-search", "hash-table", "counting"], }, "1520": { topicTags: ["greedy", "string"] }, "1521": { @@ -3921,13 +2450,7 @@ class TagsDao { topicTags: ["bit-manipulation", "string", "dynamic-programming"], }, "1526": { - topicTags: [ - "stack", - "greedy", - "array", - "dynamic-programming", - "monotonic-stack", - ], + topicTags: ["stack", "greedy", "array", "dynamic-programming", "monotonic-stack"], }, "1527": { topicTags: ["database"] }, "1528": { topicTags: ["array", "string"] }, @@ -3966,13 +2489,7 @@ class TagsDao { "1557": { topicTags: ["graph"] }, "1558": { topicTags: ["greedy", "array"] }, "1559": { - topicTags: [ - "depth-first-search", - "breadth-first-search", - "union-find", - "array", - "matrix", - ], + topicTags: ["depth-first-search", "breadth-first-search", "union-find", "array", "matrix"], }, "1560": { topicTags: ["array", "simulation"] }, "1561": { @@ -3987,13 +2504,7 @@ class TagsDao { "1566": { topicTags: ["array", "enumeration"] }, "1567": { topicTags: ["greedy", "array", "dynamic-programming"] }, "1568": { - topicTags: [ - "depth-first-search", - "breadth-first-search", - "array", - "matrix", - "strongly-connected-component", - ], + topicTags: ["depth-first-search", "breadth-first-search", "array", "matrix", "strongly-connected-component"], }, "1569": { topicTags: [ @@ -4014,13 +2525,7 @@ class TagsDao { "1572": { topicTags: ["array", "matrix"] }, "1573": { topicTags: ["math", "string"] }, "1574": { - topicTags: [ - "stack", - "array", - "two-pointers", - "binary-search", - "monotonic-stack", - ], + topicTags: ["stack", "array", "two-pointers", "binary-search", "monotonic-stack"], }, "1575": { topicTags: ["memoization", "array", "dynamic-programming"] }, "1576": { topicTags: ["string"] }, @@ -4034,14 +2539,7 @@ class TagsDao { "1584": { topicTags: ["union-find", "array", "minimum-spanning-tree"] }, "1585": { topicTags: ["greedy", "string", "sorting"] }, "1586": { - topicTags: [ - "stack", - "tree", - "design", - "binary-search-tree", - "binary-tree", - "iterator", - ], + topicTags: ["stack", "tree", "design", "binary-search-tree", "binary-tree", "iterator"], }, "1587": { topicTags: ["database"] }, "1588": { topicTags: ["array", "math", "prefix-sum"] }, @@ -4052,13 +2550,7 @@ class TagsDao { "1593": { topicTags: ["hash-table", "string", "backtracking"] }, "1594": { topicTags: ["array", "dynamic-programming", "matrix"] }, "1595": { - topicTags: [ - "bit-manipulation", - "array", - "dynamic-programming", - "bitmask", - "matrix", - ], + topicTags: ["bit-manipulation", "array", "dynamic-programming", "bitmask", "matrix"], }, "1596": { topicTags: ["database"] }, "1597": { topicTags: ["stack", "tree", "string", "binary-tree"] }, @@ -4092,13 +2584,7 @@ class TagsDao { "1615": { topicTags: ["graph"] }, "1616": { topicTags: ["two-pointers", "string"] }, "1617": { - topicTags: [ - "bit-manipulation", - "tree", - "dynamic-programming", - "bitmask", - "enumeration", - ], + topicTags: ["bit-manipulation", "tree", "dynamic-programming", "bitmask", "enumeration"], }, "1618": { topicTags: ["array", "string", "binary-search", "interactive"] }, "1619": { topicTags: ["array", "sorting"] }, @@ -4125,14 +2611,7 @@ class TagsDao { ], }, "1632": { - topicTags: [ - "greedy", - "union-find", - "graph", - "topological-sort", - "array", - "matrix", - ], + topicTags: ["greedy", "union-find", "graph", "topological-sort", "array", "matrix"], }, "1633": { topicTags: ["database"] }, "1634": { topicTags: ["linked-list", "math", "two-pointers"] }, @@ -4152,14 +2631,7 @@ class TagsDao { "1646": { topicTags: ["array", "dynamic-programming", "simulation"] }, "1647": { topicTags: ["greedy", "string", "sorting"] }, "1648": { - topicTags: [ - "greedy", - "array", - "math", - "binary-search", - "sorting", - "heap-priority-queue", - ], + topicTags: ["greedy", "array", "math", "binary-search", "sorting", "heap-priority-queue"], }, "1649": { topicTags: [ @@ -4180,41 +2652,18 @@ class TagsDao { topicTags: ["breadth-first-search", "array", "dynamic-programming"], }, "1655": { - topicTags: [ - "bit-manipulation", - "array", - "dynamic-programming", - "backtracking", - "bitmask", - ], + 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", - ], + topicTags: ["array", "hash-table", "binary-search", "prefix-sum", "sliding-window"], }, "1659": { - topicTags: [ - "bit-manipulation", - "memoization", - "dynamic-programming", - "bitmask", - ], + topicTags: ["bit-manipulation", "memoization", "dynamic-programming", "bitmask"], }, "1660": { - topicTags: [ - "tree", - "depth-first-search", - "breadth-first-search", - "hash-table", - "binary-tree", - ], + topicTags: ["tree", "depth-first-search", "breadth-first-search", "hash-table", "binary-tree"], }, "1661": { topicTags: ["database"] }, "1662": { topicTags: ["array", "string"] }, @@ -4243,12 +2692,7 @@ class TagsDao { "1679": { topicTags: ["array", "hash-table", "two-pointers", "sorting"] }, "1680": { topicTags: ["bit-manipulation", "math", "simulation"] }, "1681": { - topicTags: [ - "bit-manipulation", - "array", - "dynamic-programming", - "bitmask", - ], + topicTags: ["bit-manipulation", "array", "dynamic-programming", "bitmask"], }, "1682": { topicTags: ["string", "dynamic-programming"] }, "1683": { topicTags: ["database"] }, @@ -4257,24 +2701,10 @@ class TagsDao { }, "1685": { topicTags: ["array", "math", "prefix-sum"] }, "1686": { - topicTags: [ - "greedy", - "array", - "math", - "game-theory", - "sorting", - "heap-priority-queue", - ], + topicTags: ["greedy", "array", "math", "game-theory", "sorting", "heap-priority-queue"], }, "1687": { - topicTags: [ - "segment-tree", - "queue", - "array", - "dynamic-programming", - "monotonic-queue", - "heap-priority-queue", - ], + topicTags: ["segment-tree", "queue", "array", "dynamic-programming", "monotonic-queue", "heap-priority-queue"], }, "1688": { topicTags: ["math", "simulation"] }, "1689": { topicTags: ["greedy", "string"] }, @@ -4287,24 +2717,11 @@ class TagsDao { "1694": { topicTags: ["string"] }, "1695": { topicTags: ["array", "hash-table", "sliding-window"] }, "1696": { - topicTags: [ - "queue", - "array", - "dynamic-programming", - "sliding-window", - "monotonic-queue", - "heap-priority-queue", - ], + 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", - ], + topicTags: ["trie", "string", "suffix-array", "hash-function", "rolling-hash"], }, "1699": { topicTags: ["database"] }, "1700": { topicTags: ["stack", "queue", "array", "simulation"] }, @@ -4314,13 +2731,7 @@ class TagsDao { "1704": { topicTags: ["string", "counting"] }, "1705": { topicTags: ["greedy", "array", "heap-priority-queue"] }, "1706": { - topicTags: [ - "depth-first-search", - "array", - "dynamic-programming", - "matrix", - "simulation", - ], + topicTags: ["depth-first-search", "array", "dynamic-programming", "matrix", "simulation"], }, "1707": { topicTags: ["bit-manipulation", "trie", "array"] }, "1708": { topicTags: ["greedy", "array"] }, @@ -4341,13 +2752,7 @@ class TagsDao { "1721": { topicTags: ["linked-list", "two-pointers"] }, "1722": { topicTags: ["depth-first-search", "union-find", "array"] }, "1723": { - topicTags: [ - "bit-manipulation", - "array", - "dynamic-programming", - "backtracking", - "bitmask", - ], + topicTags: ["bit-manipulation", "array", "dynamic-programming", "backtracking", "bitmask"], }, "1724": { topicTags: ["union-find", "graph", "minimum-spanning-tree"] }, "1725": { topicTags: ["array"] }, @@ -4370,15 +2775,9 @@ class TagsDao { "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", - ], + "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"] }, @@ -4395,13 +2794,7 @@ class TagsDao { }, "1739": { topicTags: ["greedy", "math", "binary-search"] }, "1740": { - topicTags: [ - "tree", - "depth-first-search", - "breadth-first-search", - "hash-table", - "binary-tree", - ], + topicTags: ["tree", "depth-first-search", "breadth-first-search", "hash-table", "binary-tree"], }, "1741": { topicTags: ["database"] }, "1742": { topicTags: ["hash-table", "math", "counting"] }, @@ -4418,23 +2811,10 @@ class TagsDao { "1753": { topicTags: ["greedy", "math", "heap-priority-queue"] }, "1754": { topicTags: ["greedy", "two-pointers", "string"] }, "1755": { - topicTags: [ - "bit-manipulation", - "array", - "two-pointers", - "dynamic-programming", - "bitmask", - ], + topicTags: ["bit-manipulation", "array", "two-pointers", "dynamic-programming", "bitmask"], }, "1756": { - topicTags: [ - "stack", - "design", - "binary-indexed-tree", - "array", - "hash-table", - "ordered-set", - ], + topicTags: ["stack", "design", "binary-indexed-tree", "array", "hash-table", "ordered-set"], }, "1757": { topicTags: ["database"] }, "1758": { topicTags: ["string"] }, @@ -4443,13 +2823,7 @@ class TagsDao { "1761": { topicTags: ["graph"] }, "1762": { topicTags: ["stack", "array", "monotonic-stack"] }, "1763": { - topicTags: [ - "bit-manipulation", - "hash-table", - "string", - "divide-and-conquer", - "sliding-window", - ], + topicTags: ["bit-manipulation", "hash-table", "string", "divide-and-conquer", "sliding-window"], }, "1764": { topicTags: ["greedy", "array", "string-matching"] }, "1765": { topicTags: ["breadth-first-search", "array", "matrix"] }, @@ -4466,22 +2840,11 @@ class TagsDao { "1774": { topicTags: ["array", "dynamic-programming", "backtracking"] }, "1775": { topicTags: ["greedy", "array", "hash-table", "counting"] }, "1776": { - topicTags: [ - "stack", - "array", - "math", - "monotonic-stack", - "heap-priority-queue", - ], + topicTags: ["stack", "array", "math", "monotonic-stack", "heap-priority-queue"], }, "1777": { topicTags: ["database"] }, "1778": { - topicTags: [ - "depth-first-search", - "breadth-first-search", - "graph", - "interactive", - ], + topicTags: ["depth-first-search", "breadth-first-search", "graph", "interactive"], }, "1779": { topicTags: ["array"] }, "1780": { topicTags: ["math"] }, @@ -4491,13 +2854,7 @@ class TagsDao { "1784": { topicTags: ["string"] }, "1785": { topicTags: ["greedy", "array"] }, "1786": { - topicTags: [ - "graph", - "topological-sort", - "dynamic-programming", - "shortest-path", - "heap-priority-queue", - ], + topicTags: ["graph", "topological-sort", "dynamic-programming", "shortest-path", "heap-priority-queue"], }, "1787": { topicTags: ["bit-manipulation", "array", "dynamic-programming"] }, "1788": { topicTags: ["greedy", "array", "prefix-sum"] }, @@ -4506,13 +2863,7 @@ class TagsDao { "1791": { topicTags: ["graph"] }, "1792": { topicTags: ["greedy", "array", "heap-priority-queue"] }, "1793": { - topicTags: [ - "stack", - "array", - "two-pointers", - "binary-search", - "monotonic-stack", - ], + topicTags: ["stack", "array", "two-pointers", "binary-search", "monotonic-stack"], }, "1794": { topicTags: ["greedy", "hash-table", "string"] }, "1795": { topicTags: ["database"] }, @@ -4541,26 +2892,14 @@ class TagsDao { "1808": { topicTags: ["recursion", "math"] }, "1809": { topicTags: ["database"] }, "1810": { - topicTags: [ - "depth-first-search", - "breadth-first-search", - "graph", - "interactive", - "heap-priority-queue", - ], + 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", - ], + topicTags: ["bit-manipulation", "memoization", "array", "dynamic-programming", "bitmask"], }, "1816": { topicTags: ["array", "string"] }, "1817": { topicTags: ["array", "hash-table"] }, @@ -4574,13 +2913,7 @@ class TagsDao { }, "1824": { topicTags: ["greedy", "array", "dynamic-programming"] }, "1825": { - topicTags: [ - "design", - "queue", - "data-stream", - "ordered-set", - "heap-priority-queue", - ], + topicTags: ["design", "queue", "data-stream", "ordered-set", "heap-priority-queue"], }, "1826": { topicTags: ["array", "two-pointers"] }, "1827": { topicTags: ["greedy", "array"] }, @@ -4610,13 +2943,7 @@ class TagsDao { "1849": { topicTags: ["string", "backtracking"] }, "1850": { topicTags: ["greedy", "two-pointers", "string"] }, "1851": { - topicTags: [ - "array", - "binary-search", - "sorting", - "line-sweep", - "heap-priority-queue", - ], + topicTags: ["array", "binary-search", "sorting", "line-sweep", "heap-priority-queue"], }, "1852": { topicTags: ["array", "hash-table", "sliding-window"] }, "1853": { topicTags: ["database"] }, @@ -4624,14 +2951,7 @@ class TagsDao { "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", - ], + topicTags: ["graph", "topological-sort", "memoization", "hash-table", "dynamic-programming", "counting"], }, "1858": { topicTags: ["depth-first-search", "trie"] }, "1859": { topicTags: ["string", "sorting"] }, @@ -4639,13 +2959,7 @@ class TagsDao { "1861": { topicTags: ["array", "two-pointers", "matrix"] }, "1862": { topicTags: ["array", "math", "binary-search", "prefix-sum"] }, "1863": { - topicTags: [ - "bit-manipulation", - "array", - "math", - "backtracking", - "combinatorics", - ], + topicTags: ["bit-manipulation", "array", "math", "backtracking", "combinatorics"], }, "1864": { topicTags: ["greedy", "string"] }, "1865": { topicTags: ["design", "array", "hash-table"] }, @@ -4656,13 +2970,7 @@ class TagsDao { "1870": { topicTags: ["array", "binary-search"] }, "1871": { topicTags: ["two-pointers", "string", "prefix-sum"] }, "1872": { - topicTags: [ - "array", - "math", - "dynamic-programming", - "game-theory", - "prefix-sum", - ], + topicTags: ["array", "math", "dynamic-programming", "game-theory", "prefix-sum"], }, "1873": { topicTags: ["database"] }, "1874": { topicTags: ["greedy", "array", "sorting"] }, @@ -4672,22 +2980,10 @@ class TagsDao { }, "1877": { topicTags: ["greedy", "array", "two-pointers", "sorting"] }, "1878": { - topicTags: [ - "array", - "math", - "matrix", - "prefix-sum", - "sorting", - "heap-priority-queue", - ], + topicTags: ["array", "math", "matrix", "prefix-sum", "sorting", "heap-priority-queue"], }, "1879": { - topicTags: [ - "bit-manipulation", - "array", - "dynamic-programming", - "bitmask", - ], + topicTags: ["bit-manipulation", "array", "dynamic-programming", "bitmask"], }, "1880": { topicTags: ["string"] }, "1881": { topicTags: ["greedy", "string"] }, @@ -4721,37 +3017,18 @@ class TagsDao { "1903": { topicTags: ["greedy", "math", "string"] }, "1904": { topicTags: ["math", "string"] }, "1905": { - topicTags: [ - "depth-first-search", - "breadth-first-search", - "union-find", - "array", - "matrix", - ], + 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", - ], + 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", - ], + topicTags: ["design", "array", "hash-table", "ordered-set", "heap-priority-queue"], }, "1913": { topicTags: ["array", "sorting"] }, "1914": { topicTags: ["array", "matrix", "simulation"] }, @@ -4759,14 +3036,7 @@ class TagsDao { topicTags: ["bit-manipulation", "hash-table", "string", "prefix-sum"], }, "1916": { - topicTags: [ - "tree", - "graph", - "topological-sort", - "math", - "dynamic-programming", - "combinatorics", - ], + topicTags: ["tree", "graph", "topological-sort", "math", "dynamic-programming", "combinatorics"], }, "1917": { topicTags: ["database"] }, "1918": { topicTags: ["array", "binary-search", "sliding-window"] }, @@ -4775,13 +3045,7 @@ class TagsDao { "1921": { topicTags: ["greedy", "array", "sorting"] }, "1922": { topicTags: ["recursion", "math"] }, "1923": { - topicTags: [ - "array", - "binary-search", - "suffix-array", - "hash-function", - "rolling-hash", - ], + topicTags: ["array", "binary-search", "suffix-array", "hash-function", "rolling-hash"], }, "1924": { topicTags: ["geometry", "array", "math"] }, "1925": { topicTags: ["math", "enumeration"] }, @@ -4792,13 +3056,7 @@ class TagsDao { "1930": { topicTags: ["hash-table", "string", "prefix-sum"] }, "1931": { topicTags: ["dynamic-programming"] }, "1932": { - topicTags: [ - "tree", - "depth-first-search", - "hash-table", - "binary-search", - "binary-tree", - ], + topicTags: ["tree", "depth-first-search", "hash-table", "binary-search", "binary-tree"], }, "1933": { topicTags: ["string"] }, "1934": { topicTags: ["database"] }, @@ -4815,13 +3073,7 @@ class TagsDao { "1945": { topicTags: ["string", "simulation"] }, "1946": { topicTags: ["greedy", "array", "string"] }, "1947": { - topicTags: [ - "bit-manipulation", - "array", - "dynamic-programming", - "backtracking", - "bitmask", - ], + topicTags: ["bit-manipulation", "array", "dynamic-programming", "backtracking", "bitmask"], }, "1948": { topicTags: ["trie", "array", "hash-table", "string", "hash-function"], @@ -4850,34 +3102,17 @@ class TagsDao { "1968": { topicTags: ["greedy", "array", "sorting"] }, "1969": { topicTags: ["greedy", "recursion", "math"] }, "1970": { - topicTags: [ - "depth-first-search", - "breadth-first-search", - "union-find", - "array", - "binary-search", - "matrix", - ], + topicTags: ["depth-first-search", "breadth-first-search", "union-find", "array", "binary-search", "matrix"], }, "1971": { - topicTags: [ - "depth-first-search", - "breadth-first-search", - "union-find", - "graph", - ], + 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", - ], + topicTags: ["graph", "topological-sort", "dynamic-programming", "shortest-path"], }, "1977": { topicTags: ["string", "dynamic-programming", "suffix-array"] }, "1978": { topicTags: [] }, @@ -4888,23 +3123,10 @@ class TagsDao { "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", - ], + topicTags: ["array", "string", "divide-and-conquer", "quickselect", "sorting", "heap-priority-queue"], }, "1986": { - topicTags: [ - "bit-manipulation", - "array", - "dynamic-programming", - "backtracking", - "bitmask", - ], + topicTags: ["bit-manipulation", "array", "dynamic-programming", "backtracking", "bitmask"], }, "1987": { topicTags: ["string", "dynamic-programming"] }, "1988": { topicTags: [] }, @@ -4912,30 +3134,13 @@ class TagsDao { "1990": { topicTags: [] }, "1991": { topicTags: ["array", "prefix-sum"] }, "1992": { - topicTags: [ - "depth-first-search", - "breadth-first-search", - "array", - "matrix", - ], + topicTags: ["depth-first-search", "breadth-first-search", "array", "matrix"], }, "1993": { - topicTags: [ - "tree", - "depth-first-search", - "breadth-first-search", - "design", - "hash-table", - ], + topicTags: ["tree", "depth-first-search", "breadth-first-search", "design", "hash-table"], }, "1994": { - topicTags: [ - "bit-manipulation", - "array", - "math", - "dynamic-programming", - "bitmask", - ], + topicTags: ["bit-manipulation", "array", "math", "dynamic-programming", "bitmask"], }, "1995": { topicTags: ["array", "enumeration"] }, "1996": { @@ -4949,21 +3154,10 @@ class TagsDao { topicTags: ["array", "hash-table", "math", "counting", "number-theory"], }, "2002": { - topicTags: [ - "bit-manipulation", - "string", - "dynamic-programming", - "backtracking", - "bitmask", - ], + topicTags: ["bit-manipulation", "string", "dynamic-programming", "backtracking", "bitmask"], }, "2003": { - topicTags: [ - "tree", - "depth-first-search", - "union-find", - "dynamic-programming", - ], + topicTags: ["tree", "depth-first-search", "union-find", "dynamic-programming"], }, "2004": { topicTags: [] }, "2005": { topicTags: [] }, @@ -4978,13 +3172,7 @@ class TagsDao { "2012": { topicTags: ["array"] }, "2013": { topicTags: ["design", "array", "hash-table", "counting"] }, "2014": { - topicTags: [ - "greedy", - "string", - "backtracking", - "counting", - "enumeration", - ], + topicTags: ["greedy", "string", "backtracking", "counting", "enumeration"], }, "2015": { topicTags: ["greedy", "array", "sorting", "heap-priority-queue"], @@ -4993,30 +3181,17 @@ class TagsDao { "2017": { topicTags: ["array", "matrix", "prefix-sum"] }, "2018": { topicTags: ["array", "enumeration", "matrix"] }, "2019": { - topicTags: [ - "stack", - "memoization", - "array", - "math", - "string", - "dynamic-programming", - ], + 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", - ], + "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"] }, @@ -5039,13 +3214,7 @@ class TagsDao { "2032": { topicTags: ["array", "hash-table"] }, "2033": { topicTags: ["array", "math", "matrix", "sorting"] }, "2034": { - topicTags: [ - "design", - "hash-table", - "data-stream", - "ordered-set", - "heap-priority-queue", - ], + topicTags: ["design", "hash-table", "data-stream", "ordered-set", "heap-priority-queue"], }, "2035": { topicTags: [ @@ -5079,13 +3248,7 @@ class TagsDao { "2052": { topicTags: ["array", "dynamic-programming"] }, "2053": { topicTags: ["array", "hash-table", "string", "counting"] }, "2054": { - topicTags: [ - "array", - "binary-search", - "dynamic-programming", - "sorting", - "heap-priority-queue", - ], + topicTags: ["array", "binary-search", "dynamic-programming", "sorting", "heap-priority-queue"], }, "2055": { topicTags: ["array", "string", "binary-search", "prefix-sum"] }, "2056": { topicTags: ["array", "string", "backtracking", "simulation"] }, @@ -5106,14 +3269,7 @@ class TagsDao { "2069": { topicTags: ["design", "simulation"] }, "2070": { topicTags: ["array", "binary-search", "sorting"] }, "2071": { - topicTags: [ - "greedy", - "queue", - "array", - "binary-search", - "sorting", - "monotonic-queue", - ], + topicTags: ["greedy", "queue", "array", "binary-search", "sorting", "monotonic-queue"], }, "2072": { topicTags: ["database"] }, "2073": { topicTags: ["queue", "array", "simulation"] }, @@ -5124,13 +3280,7 @@ class TagsDao { "2078": { topicTags: ["greedy", "array"] }, "2079": { topicTags: ["array"] }, "2080": { - topicTags: [ - "design", - "segment-tree", - "array", - "hash-table", - "binary-search", - ], + topicTags: ["design", "segment-tree", "array", "hash-table", "binary-search"], }, "2081": { topicTags: ["math", "enumeration"] }, "2082": { topicTags: ["database"] }, @@ -5146,13 +3296,7 @@ class TagsDao { "2090": { topicTags: ["array", "sliding-window"] }, "2091": { topicTags: ["greedy", "array"] }, "2092": { - topicTags: [ - "depth-first-search", - "breadth-first-search", - "union-find", - "graph", - "sorting", - ], + topicTags: ["depth-first-search", "breadth-first-search", "union-find", "graph", "sorting"], }, "2093": { topicTags: ["graph", "shortest-path"] }, "2094": { topicTags: ["array", "hash-table", "enumeration", "sorting"] }, @@ -5167,22 +3311,10 @@ class TagsDao { }, "2100": { topicTags: ["array", "dynamic-programming", "prefix-sum"] }, "2101": { - topicTags: [ - "depth-first-search", - "breadth-first-search", - "graph", - "geometry", - "array", - "math", - ], + topicTags: ["depth-first-search", "breadth-first-search", "graph", "geometry", "array", "math"], }, "2102": { - topicTags: [ - "design", - "data-stream", - "ordered-set", - "heap-priority-queue", - ], + topicTags: ["design", "data-stream", "ordered-set", "heap-priority-queue"], }, "2103": { topicTags: ["hash-table", "string"] }, "2104": { topicTags: ["stack", "array", "monotonic-stack"] }, @@ -5223,13 +3355,7 @@ class TagsDao { "2133": { topicTags: ["array", "hash-table", "matrix"] }, "2134": { topicTags: ["array", "sliding-window"] }, "2135": { - topicTags: [ - "bit-manipulation", - "array", - "hash-table", - "string", - "sorting", - ], + topicTags: ["bit-manipulation", "array", "hash-table", "string", "sorting"], }, "2136": { topicTags: ["greedy", "array", "sorting"] }, "2137": { topicTags: ["array", "binary-search"] }, @@ -5242,13 +3368,7 @@ class TagsDao { "2144": { topicTags: ["greedy", "array", "sorting"] }, "2145": { topicTags: ["array", "prefix-sum"] }, "2146": { - topicTags: [ - "breadth-first-search", - "array", - "matrix", - "sorting", - "heap-priority-queue", - ], + topicTags: ["breadth-first-search", "array", "matrix", "sorting", "heap-priority-queue"], }, "2147": { topicTags: ["math", "string", "dynamic-programming"] }, "2148": { topicTags: ["array", "sorting"] }, @@ -5289,33 +3409,17 @@ class TagsDao { "2166": { topicTags: ["design", "array", "hash-table"] }, "2167": { topicTags: ["string", "dynamic-programming"] }, "2168": { - topicTags: [ - "hash-table", - "string", - "counting", - "hash-function", - "rolling-hash", - ], + 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", - ], + topicTags: ["bit-manipulation", "array", "dynamic-programming", "bitmask"], }, "2173": { topicTags: ["database"] }, "2174": { - topicTags: [ - "bit-manipulation", - "breadth-first-search", - "array", - "matrix", - ], + topicTags: ["bit-manipulation", "breadth-first-search", "array", "matrix"], }, "2175": { topicTags: ["database"] }, "2176": { topicTags: ["array"] }, @@ -5339,12 +3443,7 @@ class TagsDao { }, "2183": { topicTags: ["array", "math", "number-theory"] }, "2184": { - topicTags: [ - "bit-manipulation", - "array", - "dynamic-programming", - "bitmask", - ], + topicTags: ["bit-manipulation", "array", "dynamic-programming", "bitmask"], }, "2185": { topicTags: ["array", "string"] }, "2186": { topicTags: ["hash-table", "string", "counting"] }, @@ -5354,12 +3453,7 @@ class TagsDao { "2190": { topicTags: ["array", "hash-table", "counting"] }, "2191": { topicTags: ["array", "sorting"] }, "2192": { - topicTags: [ - "depth-first-search", - "breadth-first-search", - "graph", - "topological-sort", - ], + topicTags: ["depth-first-search", "breadth-first-search", "graph", "topological-sort"], }, "2193": { topicTags: ["greedy", "binary-indexed-tree", "two-pointers", "string"], @@ -5367,14 +3461,7 @@ class TagsDao { "2194": { topicTags: ["string"] }, "2195": { topicTags: ["greedy", "array", "math", "sorting"] }, "2196": { - topicTags: [ - "tree", - "depth-first-search", - "breadth-first-search", - "array", - "hash-table", - "binary-tree", - ], + topicTags: ["tree", "depth-first-search", "breadth-first-search", "array", "hash-table", "binary-tree"], }, "2197": { topicTags: ["stack", "array", "math", "number-theory"] }, "2198": { topicTags: ["math"] }, @@ -5384,12 +3471,7 @@ class TagsDao { "2202": { topicTags: ["greedy", "array"] }, "2203": { topicTags: ["graph", "shortest-path"] }, "2204": { - topicTags: [ - "depth-first-search", - "breadth-first-search", - "union-find", - "graph", - ], + topicTags: ["depth-first-search", "breadth-first-search", "union-find", "graph"], }, "2205": { topicTags: ["database"] }, "2206": { @@ -5414,14 +3496,7 @@ class TagsDao { "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", - ], + topicTags: ["string", "binary-search", "string-matching", "suffix-array", "hash-function", "rolling-hash"], }, "2224": { topicTags: ["greedy", "string"] }, "2225": { topicTags: ["array", "hash-table", "counting", "sorting"] }, @@ -5434,13 +3509,7 @@ class TagsDao { "2232": { topicTags: ["string", "enumeration"] }, "2233": { topicTags: ["greedy", "array", "heap-priority-queue"] }, "2234": { - topicTags: [ - "greedy", - "array", - "two-pointers", - "binary-search", - "sorting", - ], + topicTags: ["greedy", "array", "two-pointers", "binary-search", "sorting"], }, "2235": { topicTags: ["math"] }, "2236": { topicTags: ["tree", "binary-tree"] }, @@ -5454,22 +3523,10 @@ class TagsDao { "2244": { topicTags: ["greedy", "array", "hash-table", "counting"] }, "2245": { topicTags: ["array", "matrix", "prefix-sum"] }, "2246": { - topicTags: [ - "tree", - "depth-first-search", - "graph", - "topological-sort", - "array", - "string", - ], + topicTags: ["tree", "depth-first-search", "graph", "topological-sort", "array", "string"], }, "2247": { - topicTags: [ - "bit-manipulation", - "graph", - "dynamic-programming", - "bitmask", - ], + topicTags: ["bit-manipulation", "graph", "dynamic-programming", "bitmask"], }, "2248": { topicTags: ["array", "hash-table", "counting"] }, "2249": { @@ -5479,14 +3536,7 @@ class TagsDao { topicTags: ["binary-indexed-tree", "array", "binary-search", "sorting"], }, "2251": { - topicTags: [ - "array", - "hash-table", - "binary-search", - "ordered-set", - "prefix-sum", - "sorting", - ], + topicTags: ["array", "hash-table", "binary-search", "ordered-set", "prefix-sum", "sorting"], }, "2252": { topicTags: ["database"] }, "2253": { topicTags: ["database"] }, @@ -5500,14 +3550,7 @@ class TagsDao { "2259": { topicTags: ["greedy", "string", "enumeration"] }, "2260": { topicTags: ["array", "hash-table", "sliding-window"] }, "2261": { - topicTags: [ - "trie", - "array", - "hash-table", - "enumeration", - "hash-function", - "rolling-hash", - ], + topicTags: ["trie", "array", "hash-table", "enumeration", "hash-function", "rolling-hash"], }, "2262": { topicTags: ["hash-table", "string", "dynamic-programming"] }, "2263": { topicTags: ["greedy", "dynamic-programming"] }, @@ -5531,12 +3574,7 @@ class TagsDao { }, "2276": { topicTags: ["design", "segment-tree", "ordered-set"] }, "2277": { - topicTags: [ - "tree", - "depth-first-search", - "breadth-first-search", - "array", - ], + topicTags: ["tree", "depth-first-search", "breadth-first-search", "array"], }, "2278": { topicTags: ["string"] }, "2279": { topicTags: ["greedy", "array", "sorting"] }, @@ -5551,25 +3589,13 @@ class TagsDao { topicTags: ["greedy", "graph", "sorting", "heap-priority-queue"], }, "2286": { - topicTags: [ - "design", - "binary-indexed-tree", - "segment-tree", - "binary-search", - ], + 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", - ], + topicTags: ["breadth-first-search", "graph", "array", "matrix", "shortest-path", "heap-priority-queue"], }, "2291": { topicTags: ["array", "dynamic-programming"] }, "2292": { topicTags: ["database"] }, @@ -5577,24 +3603,10 @@ class TagsDao { "2294": { topicTags: ["greedy", "array", "sorting"] }, "2295": { topicTags: ["array", "hash-table", "simulation"] }, "2296": { - topicTags: [ - "stack", - "design", - "linked-list", - "string", - "doubly-linked-list", - "simulation", - ], + topicTags: ["stack", "design", "linked-list", "string", "doubly-linked-list", "simulation"], }, "2297": { - topicTags: [ - "stack", - "graph", - "array", - "dynamic-programming", - "shortest-path", - "monotonic-stack", - ], + topicTags: ["stack", "graph", "array", "dynamic-programming", "shortest-path", "monotonic-stack"], }, "2298": { topicTags: ["database"] }, "2299": { topicTags: ["string"] }, @@ -5608,22 +3620,10 @@ class TagsDao { "2303": { topicTags: ["array", "simulation"] }, "2304": { topicTags: ["array", "dynamic-programming", "matrix"] }, "2305": { - topicTags: [ - "bit-manipulation", - "array", - "dynamic-programming", - "backtracking", - "bitmask", - ], + topicTags: ["bit-manipulation", "array", "dynamic-programming", "backtracking", "bitmask"], }, "2306": { - topicTags: [ - "bit-manipulation", - "array", - "hash-table", - "string", - "enumeration", - ], + topicTags: ["bit-manipulation", "array", "hash-table", "string", "enumeration"], }, "2307": { topicTags: ["depth-first-search", "union-find", "graph", "array"], @@ -5638,22 +3638,12 @@ class TagsDao { }, "2312": { topicTags: ["memoization", "array", "dynamic-programming"] }, "2313": { - topicTags: [ - "tree", - "depth-first-search", - "dynamic-programming", - "binary-tree", - ], + 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", - ], + topicTags: ["depth-first-search", "breadth-first-search", "union-find", "graph"], }, "2317": { topicTags: ["bit-manipulation", "array", "math"] }, "2318": { topicTags: ["memoization", "dynamic-programming"] }, @@ -5692,12 +3682,7 @@ class TagsDao { "2336": { topicTags: ["design", "hash-table", "heap-priority-queue"] }, "2337": { topicTags: ["two-pointers", "string"] }, "2338": { - topicTags: [ - "math", - "dynamic-programming", - "combinatorics", - "number-theory", - ], + topicTags: ["math", "dynamic-programming", "combinatorics", "number-theory"], }, "2339": { topicTags: ["database"] }, "2340": { topicTags: ["greedy", "array"] }, @@ -5717,13 +3702,7 @@ class TagsDao { ], }, "2344": { - topicTags: [ - "array", - "math", - "number-theory", - "sorting", - "heap-priority-queue", - ], + topicTags: ["array", "math", "number-theory", "sorting", "heap-priority-queue"], }, "2345": { topicTags: ["stack", "array", "sorting", "monotonic-stack"] }, "2346": { topicTags: ["database"] }, @@ -5746,13 +3725,7 @@ class TagsDao { }, "2356": { topicTags: ["database"] }, "2357": { - topicTags: [ - "array", - "hash-table", - "sorting", - "simulation", - "heap-priority-queue", - ], + topicTags: ["array", "hash-table", "sorting", "simulation", "heap-priority-queue"], }, "2358": { topicTags: ["greedy", "array", "math", "binary-search"] }, "2359": { topicTags: ["depth-first-search", "graph"] }, @@ -5767,27 +3740,12 @@ class TagsDao { topicTags: ["array", "hash-table", "two-pointers", "enumeration"], }, "2368": { - topicTags: [ - "tree", - "depth-first-search", - "breadth-first-search", - "graph", - "array", - "hash-table", - ], + 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", - ], + topicTags: ["greedy", "union-find", "graph", "topological-sort", "array", "matrix", "sorting"], }, "2372": { topicTags: ["database"] }, "2373": { topicTags: ["array", "matrix"] }, @@ -5805,12 +3763,7 @@ class TagsDao { "2383": { topicTags: ["greedy", "array"] }, "2384": { topicTags: ["greedy", "hash-table", "string"] }, "2385": { - topicTags: [ - "tree", - "depth-first-search", - "breadth-first-search", - "binary-tree", - ], + topicTags: ["tree", "depth-first-search", "breadth-first-search", "binary-tree"], }, "2386": { topicTags: ["array", "sorting", "heap-priority-queue"] }, "2387": { topicTags: ["array", "binary-search", "matrix"] }, @@ -5821,52 +3774,27 @@ class TagsDao { "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", - ], + "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", - ], + 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", - ], + 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", - ], + topicTags: ["greedy", "array", "two-pointers", "prefix-sum", "sorting", "heap-priority-queue"], }, "2407": { topicTags: [ @@ -5883,23 +3811,13 @@ class TagsDao { "2409": { topicTags: ["math", "string"] }, "2410": { topicTags: ["greedy", "array", "two-pointers", "sorting"] }, "2411": { - topicTags: [ - "bit-manipulation", - "array", - "binary-search", - "sliding-window", - ], + 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", - ], + topicTags: ["tree", "depth-first-search", "breadth-first-search", "binary-tree"], }, "2416": { topicTags: ["trie", "array", "string", "counting"] }, "2417": { topicTags: ["math", "enumeration"] }, @@ -5911,54 +3829,26 @@ class TagsDao { "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", - ], + 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", - ], + 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", - ], + topicTags: ["breadth-first-search", "segment-tree", "array", "dynamic-programming"], }, "LCP 10": { - topicTags: [ - "tree", - "depth-first-search", - "dynamic-programming", - "binary-tree", - ], + 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", - ], + topicTags: ["bit-manipulation", "breadth-first-search", "array", "dynamic-programming", "bitmask", "matrix"], }, "LCP 14": { topicTags: ["array", "math", "dynamic-programming", "number-theory"], @@ -5972,12 +3862,7 @@ class TagsDao { "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", - ], + topicTags: ["depth-first-search", "breadth-first-search", "graph", "topological-sort"], }, "LCP 22": { topicTags: ["math"] }, "LCP 23": { topicTags: ["queue", "array", "simulation"] }, @@ -5991,13 +3876,7 @@ class TagsDao { "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", - ], + 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"] }, @@ -6005,38 +3884,18 @@ class TagsDao { "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", - ], + 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", - ], + 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", - ], + topicTags: ["tree", "depth-first-search", "breadth-first-search", "hash-table", "binary-tree"], }, "LCP 45": { topicTags: [ @@ -6052,47 +3911,22 @@ class TagsDao { "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", - ], + 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", - ], + topicTags: ["tree", "segment-tree", "binary-search-tree", "array", "binary-search", "binary-tree", "ordered-set"], }, "LCP 53": { - topicTags: [ - "bit-manipulation", - "array", - "dynamic-programming", - "bitmask", - ], + 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", - ], + topicTags: ["breadth-first-search", "graph", "array", "matrix", "shortest-path", "heap-priority-queue"], }, "LCP 57": { topicTags: ["array", "dynamic-programming", "matrix", "sorting"], @@ -6108,13 +3942,7 @@ class TagsDao { "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", - ], + topicTags: ["depth-first-search", "breadth-first-search", "union-find", "array", "matrix"], }, "剑指 Offer 03": { topicTags: ["array", "hash-table", "sorting"] }, "剑指 Offer 04": { @@ -6125,13 +3953,7 @@ class TagsDao { topicTags: ["stack", "recursion", "linked-list", "two-pointers"], }, "剑指 Offer 07": { - topicTags: [ - "tree", - "array", - "hash-table", - "divide-and-conquer", - "binary-tree", - ], + topicTags: ["tree", "array", "hash-table", "divide-and-conquer", "binary-tree"], }, "剑指 Offer 09": { topicTags: ["stack", "design", "queue"] }, "剑指 Offer 10- I": { @@ -6160,20 +3982,10 @@ class TagsDao { topicTags: ["tree", "depth-first-search", "binary-tree"], }, "剑指 Offer 27": { - topicTags: [ - "tree", - "depth-first-search", - "breadth-first-search", - "binary-tree", - ], + topicTags: ["tree", "depth-first-search", "breadth-first-search", "binary-tree"], }, "剑指 Offer 28": { - topicTags: [ - "tree", - "depth-first-search", - "breadth-first-search", - "binary-tree", - ], + topicTags: ["tree", "depth-first-search", "breadth-first-search", "binary-tree"], }, "剑指 Offer 29": { topicTags: ["array", "matrix", "simulation"] }, "剑指 Offer 30": { topicTags: ["stack", "design"] }, @@ -6188,14 +4000,7 @@ class TagsDao { topicTags: ["tree", "breadth-first-search", "binary-tree"], }, "剑指 Offer 33": { - topicTags: [ - "stack", - "tree", - "binary-search-tree", - "recursion", - "binary-tree", - "monotonic-stack", - ], + topicTags: ["stack", "tree", "binary-search-tree", "recursion", "binary-tree", "monotonic-stack"], }, "剑指 Offer 34": { topicTags: ["tree", "depth-first-search", "backtracking", "binary-tree"], @@ -6213,42 +4018,17 @@ class TagsDao { ], }, "剑指 Offer 37": { - topicTags: [ - "tree", - "depth-first-search", - "breadth-first-search", - "design", - "string", - "binary-tree", - ], + 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", - ], + topicTags: ["array", "hash-table", "divide-and-conquer", "counting", "sorting"], }, "剑指 Offer 40": { - topicTags: [ - "array", - "divide-and-conquer", - "quickselect", - "sorting", - "heap-priority-queue", - ], + topicTags: ["array", "divide-and-conquer", "quickselect", "sorting", "heap-priority-queue"], }, "剑指 Offer 41": { - topicTags: [ - "design", - "two-pointers", - "data-stream", - "sorting", - "heap-priority-queue", - ], + topicTags: ["design", "two-pointers", "data-stream", "sorting", "heap-priority-queue"], }, "剑指 Offer 42": { topicTags: ["array", "divide-and-conquer", "dynamic-programming"], @@ -6262,12 +4042,7 @@ class TagsDao { "剑指 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", - ], + topicTags: ["hash-table", "math", "dynamic-programming", "heap-priority-queue"], }, "剑指 Offer 50": { topicTags: ["queue", "hash-table", "string", "counting"], @@ -6288,29 +4063,13 @@ class TagsDao { }, "剑指 Offer 53 - I": { topicTags: ["array", "binary-search"] }, "剑指 Offer 53 - II": { - topicTags: [ - "bit-manipulation", - "array", - "hash-table", - "math", - "binary-search", - ], + topicTags: ["bit-manipulation", "array", "hash-table", "math", "binary-search"], }, "剑指 Offer 54": { - topicTags: [ - "tree", - "depth-first-search", - "binary-search-tree", - "binary-tree", - ], + topicTags: ["tree", "depth-first-search", "binary-search-tree", "binary-tree"], }, "剑指 Offer 55 - I": { - topicTags: [ - "tree", - "depth-first-search", - "breadth-first-search", - "binary-tree", - ], + topicTags: ["tree", "depth-first-search", "breadth-first-search", "binary-tree"], }, "剑指 Offer 55 - II": { topicTags: ["tree", "depth-first-search", "binary-tree"], @@ -6324,12 +4083,7 @@ class TagsDao { "剑指 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", - ], + topicTags: ["queue", "sliding-window", "monotonic-queue", "heap-priority-queue"], }, "剑指 Offer 60": { topicTags: ["math", "dynamic-programming", "probability-and-statistics"], @@ -6344,12 +4098,7 @@ class TagsDao { "剑指 Offer 66": { topicTags: ["array", "prefix-sum"] }, "剑指 Offer 67": { topicTags: ["string"] }, "剑指 Offer 68 - I": { - topicTags: [ - "tree", - "depth-first-search", - "binary-search-tree", - "binary-tree", - ], + topicTags: ["tree", "depth-first-search", "binary-search-tree", "binary-tree"], }, "剑指 Offer 68 - II": { topicTags: ["tree", "depth-first-search", "binary-tree"], @@ -6428,13 +4177,7 @@ class TagsDao { "剑指 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", - ], + topicTags: ["stack", "array", "dynamic-programming", "matrix", "monotonic-stack"], }, "剑指 Offer II 041": { topicTags: ["design", "queue", "array", "data-stream"], @@ -6444,41 +4187,19 @@ class TagsDao { topicTags: ["tree", "breadth-first-search", "design", "binary-tree"], }, "剑指 Offer II 044": { - topicTags: [ - "tree", - "depth-first-search", - "breadth-first-search", - "binary-tree", - ], + topicTags: ["tree", "depth-first-search", "breadth-first-search", "binary-tree"], }, "剑指 Offer II 045": { - topicTags: [ - "tree", - "depth-first-search", - "breadth-first-search", - "binary-tree", - ], + topicTags: ["tree", "depth-first-search", "breadth-first-search", "binary-tree"], }, "剑指 Offer II 046": { - topicTags: [ - "tree", - "depth-first-search", - "breadth-first-search", - "binary-tree", - ], + 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", - ], + topicTags: ["tree", "depth-first-search", "breadth-first-search", "design", "string", "binary-tree"], }, "剑指 Offer II 049": { topicTags: ["tree", "depth-first-search", "binary-tree"], @@ -6487,47 +4208,19 @@ class TagsDao { topicTags: ["tree", "depth-first-search", "binary-tree"], }, "剑指 Offer II 051": { - topicTags: [ - "tree", - "depth-first-search", - "dynamic-programming", - "binary-tree", - ], + topicTags: ["tree", "depth-first-search", "dynamic-programming", "binary-tree"], }, "剑指 Offer II 052": { - topicTags: [ - "stack", - "tree", - "depth-first-search", - "binary-search-tree", - "binary-tree", - ], + topicTags: ["stack", "tree", "depth-first-search", "binary-search-tree", "binary-tree"], }, "剑指 Offer II 053": { - topicTags: [ - "tree", - "depth-first-search", - "binary-search-tree", - "binary-tree", - ], + topicTags: ["tree", "depth-first-search", "binary-search-tree", "binary-tree"], }, "剑指 Offer II 054": { - topicTags: [ - "tree", - "depth-first-search", - "binary-search-tree", - "binary-tree", - ], + topicTags: ["tree", "depth-first-search", "binary-search-tree", "binary-tree"], }, "剑指 Offer II 055": { - topicTags: [ - "stack", - "tree", - "design", - "binary-search-tree", - "binary-tree", - "iterator", - ], + topicTags: ["stack", "tree", "design", "binary-search-tree", "binary-tree", "iterator"], }, "剑指 Offer II 056": { topicTags: [ @@ -6541,26 +4234,13 @@ class TagsDao { ], }, "剑指 Offer II 057": { - topicTags: [ - "array", - "bucket-sort", - "ordered-set", - "sorting", - "sliding-window", - ], + 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", - ], + topicTags: ["tree", "design", "binary-search-tree", "binary-tree", "data-stream", "heap-priority-queue"], }, "剑指 Offer II 060": { topicTags: [ @@ -6606,30 +4286,13 @@ class TagsDao { topicTags: ["array", "hash-table", "counting-sort", "sorting"], }, "剑指 Offer II 076": { - topicTags: [ - "array", - "divide-and-conquer", - "quickselect", - "sorting", - "heap-priority-queue", - ], + topicTags: ["array", "divide-and-conquer", "quickselect", "sorting", "heap-priority-queue"], }, "剑指 Offer II 077": { - topicTags: [ - "linked-list", - "two-pointers", - "divide-and-conquer", - "sorting", - "merge-sort", - ], + 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", - ], + topicTags: ["linked-list", "divide-and-conquer", "heap-priority-queue", "merge-sort"], }, "剑指 Offer II 079": { topicTags: ["bit-manipulation", "array", "backtracking"], @@ -6643,12 +4306,7 @@ class TagsDao { topicTags: ["string", "dynamic-programming", "backtracking"], }, "剑指 Offer II 086": { - topicTags: [ - "depth-first-search", - "breadth-first-search", - "graph", - "hash-table", - ], + topicTags: ["depth-first-search", "breadth-first-search", "graph", "hash-table"], }, "剑指 Offer II 087": { topicTags: ["string", "backtracking"] }, "剑指 Offer II 088": { topicTags: ["array", "dynamic-programming"] }, @@ -6679,29 +4337,13 @@ class TagsDao { }, "剑指 Offer II 104": { topicTags: ["array", "dynamic-programming"] }, "剑指 Offer II 105": { - topicTags: [ - "depth-first-search", - "breadth-first-search", - "union-find", - "array", - "matrix", - ], + topicTags: ["depth-first-search", "breadth-first-search", "union-find", "array", "matrix"], }, "剑指 Offer II 106": { - topicTags: [ - "depth-first-search", - "breadth-first-search", - "union-find", - "graph", - ], + topicTags: ["depth-first-search", "breadth-first-search", "union-find", "graph"], }, "剑指 Offer II 107": { - topicTags: [ - "breadth-first-search", - "array", - "dynamic-programming", - "matrix", - ], + topicTags: ["breadth-first-search", "array", "dynamic-programming", "matrix"], }, "剑指 Offer II 108": { topicTags: ["breadth-first-search", "hash-table", "string"], @@ -6710,22 +4352,10 @@ class TagsDao { topicTags: ["breadth-first-search", "array", "hash-table", "string"], }, "剑指 Offer II 110": { - topicTags: [ - "depth-first-search", - "breadth-first-search", - "graph", - "backtracking", - ], + 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", - ], + topicTags: ["depth-first-search", "breadth-first-search", "union-find", "graph", "array", "shortest-path"], }, "剑指 Offer II 112": { topicTags: [ @@ -6740,48 +4370,20 @@ class TagsDao { ], }, "剑指 Offer II 113": { - topicTags: [ - "depth-first-search", - "breadth-first-search", - "graph", - "topological-sort", - ], + 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", - ], + 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", - ], + topicTags: ["depth-first-search", "breadth-first-search", "union-find", "graph"], }, "剑指 Offer II 117": { - topicTags: [ - "depth-first-search", - "breadth-first-search", - "union-find", - "array", - "string", - ], + topicTags: ["depth-first-search", "breadth-first-search", "union-find", "array", "string"], }, "剑指 Offer II 118": { - topicTags: [ - "depth-first-search", - "breadth-first-search", - "union-find", - "graph", - ], + topicTags: ["depth-first-search", "breadth-first-search", "union-find", "graph"], }, "剑指 Offer II 119": { topicTags: ["union-find", "array", "hash-table"] }, "面试题 01.01": { @@ -6818,21 +4420,10 @@ class TagsDao { "面试题 03.05": { topicTags: ["stack", "design", "monotonic-stack"] }, "面试题 03.06": { topicTags: ["design", "queue"] }, "面试题 04.01": { - topicTags: [ - "depth-first-search", - "breadth-first-search", - "union-find", - "graph", - ], + topicTags: ["depth-first-search", "breadth-first-search", "union-find", "graph"], }, "面试题 04.02": { - topicTags: [ - "tree", - "binary-search-tree", - "array", - "divide-and-conquer", - "binary-tree", - ], + topicTags: ["tree", "binary-search-tree", "array", "divide-and-conquer", "binary-tree"], }, "面试题 04.03": { topicTags: ["tree", "breadth-first-search", "linked-list", "binary-tree"], @@ -6841,20 +4432,10 @@ class TagsDao { topicTags: ["tree", "depth-first-search", "binary-tree"], }, "面试题 04.05": { - topicTags: [ - "tree", - "depth-first-search", - "binary-search-tree", - "binary-tree", - ], + topicTags: ["tree", "depth-first-search", "binary-search-tree", "binary-tree"], }, "面试题 04.06": { - topicTags: [ - "tree", - "depth-first-search", - "binary-search-tree", - "binary-tree", - ], + topicTags: ["tree", "depth-first-search", "binary-search-tree", "binary-tree"], }, "面试题 04.08": { topicTags: ["tree", "depth-first-search", "binary-tree"], @@ -6863,13 +4444,7 @@ class TagsDao { topicTags: ["tree", "binary-search-tree", "backtracking", "binary-tree"], }, "面试题 04.10": { - topicTags: [ - "tree", - "depth-first-search", - "binary-tree", - "string-matching", - "hash-function", - ], + topicTags: ["tree", "depth-first-search", "binary-tree", "string-matching", "hash-function"], }, "面试题 04.12": { topicTags: ["tree", "depth-first-search", "binary-tree"], @@ -6899,12 +4474,7 @@ class TagsDao { topicTags: ["string", "dynamic-programming", "backtracking"], }, "面试题 08.10": { - topicTags: [ - "depth-first-search", - "breadth-first-search", - "array", - "matrix", - ], + topicTags: ["depth-first-search", "breadth-first-search", "array", "matrix"], }, "面试题 08.11": { topicTags: ["array", "math", "dynamic-programming"] }, "面试题 08.12": { topicTags: ["array", "backtracking"] }, @@ -6920,12 +4490,7 @@ class TagsDao { topicTags: ["array", "binary-search", "divide-and-conquer", "matrix"], }, "面试题 10.10": { - topicTags: [ - "design", - "binary-indexed-tree", - "binary-search", - "data-stream", - ], + topicTags: ["design", "binary-indexed-tree", "binary-search", "data-stream"], }, "面试题 10.11": { topicTags: ["greedy", "array", "sorting"] }, "面试题 16.01": { topicTags: ["bit-manipulation", "math"] }, @@ -6947,14 +4512,7 @@ class TagsDao { "面试题 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", - ], + topicTags: ["stack", "greedy", "array", "two-pointers", "sorting", "monotonic-stack"], }, "面试题 16.17": { topicTags: ["array", "divide-and-conquer", "dynamic-programming"], @@ -6963,13 +4521,7 @@ class TagsDao { topicTags: ["math", "string", "backtracking", "enumeration"], }, "面试题 16.19": { - topicTags: [ - "depth-first-search", - "breadth-first-search", - "union-find", - "array", - "matrix", - ], + topicTags: ["depth-first-search", "breadth-first-search", "union-find", "array", "matrix"], }, "面试题 16.20": { topicTags: ["array", "hash-table", "string"] }, "面试题 16.21": { @@ -7006,84 +4558,34 @@ class TagsDao { topicTags: ["array", "binary-search", "dynamic-programming", "sorting"], }, "面试题 17.09": { - topicTags: [ - "hash-table", - "math", - "dynamic-programming", - "heap-priority-queue", - ], + 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", - ], + 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", - ], + topicTags: ["trie", "array", "hash-table", "string", "dynamic-programming", "hash-function", "rolling-hash"], }, "面试题 17.14": { - topicTags: [ - "array", - "divide-and-conquer", - "quickselect", - "sorting", - "heap-priority-queue", - ], + 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", - ], + 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", - ], + topicTags: ["design", "two-pointers", "data-stream", "sorting", "heap-priority-queue"], }, "面试题 17.21": { - topicTags: [ - "stack", - "array", - "two-pointers", - "dynamic-programming", - "monotonic-stack", - ], + topicTags: ["stack", "array", "two-pointers", "dynamic-programming", "monotonic-stack"], }, "面试题 17.22": { - topicTags: [ - "breadth-first-search", - "hash-table", - "string", - "backtracking", - ], + topicTags: ["breadth-first-search", "hash-table", "string", "backtracking"], }, "面试题 17.23": { topicTags: ["array", "dynamic-programming", "matrix"] }, "面试题 17.24": { @@ -7092,11 +4594,7 @@ class TagsDao { "面试题 17.25": { topicTags: ["trie", "array", "string", "backtracking"] }, "面试题 17.26": { topicTags: ["array", "hash-table", "sorting"] }, 面试题13: { - topicTags: [ - "depth-first-search", - "breadth-first-search", - "dynamic-programming", - ], + topicTags: ["depth-first-search", "breadth-first-search", "dynamic-programming"], }, "面试题59 - II": { topicTags: ["design", "queue", "monotonic-queue"] }, }; diff --git a/src/extension.ts b/src/extension.ts index 1b5ff31..7b11ec2 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -52,71 +52,32 @@ export async function activate(context: ExtensionContext): Promise { 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() - ) + 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()) ); // 设置站点 diff --git a/src/model/NodeModel.ts b/src/model/NodeModel.ts index e4c3b52..b1b2448 100644 --- a/src/model/NodeModel.ts +++ b/src/model/NodeModel.ts @@ -8,21 +8,11 @@ */ import { Command, Uri } from "vscode"; -import { - IProblem, - IScoreData, - ITodayData, - ProblemState, - RootNodeSort, -} from "./Model"; +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 - ) { + constructor(private data: IProblem, private isProblemNode: boolean = true, userscore: number = 0) { this._u_score = userscore; } diff --git a/src/rpc/actionChain/chainManager.ts b/src/rpc/actionChain/chainManager.ts index a870e20..2c0c833 100644 --- a/src/rpc/actionChain/chainManager.ts +++ b/src/rpc/actionChain/chainManager.ts @@ -34,9 +34,7 @@ export class ChainManager { this.head = head; } const stats = storageUtils.getCache(commUtils.KEYS.plugins) || {}; - let fileChainNode: Array = storageUtils.listCodeDir( - "../actionChain/chainNode" - ); + let fileChainNode: Array = storageUtils.listCodeDir("../actionChain/chainNode"); this.installed = []; for (let f of fileChainNode) { const p = f.data; diff --git a/src/rpc/actionChain/chainNode/cache.ts b/src/rpc/actionChain/chainNode/cache.ts index 5117064..05c40e0 100644 --- a/src/rpc/actionChain/chainNode/cache.ts +++ b/src/rpc/actionChain/chainNode/cache.ts @@ -25,10 +25,7 @@ class CachePlugin extends ChainNodeBase { clearCacheIfTchanged = (needTranslation) => { const translationConfig = storageUtils.getCache(commUtils.KEYS.translation); - if ( - !translationConfig || - translationConfig["useEndpointTranslation"] != needTranslation - ) { + if (!translationConfig || translationConfig["useEndpointTranslation"] != needTranslation) { storageUtils.deleteAllCache(); storageUtils.setCache(commUtils.KEYS.translation, { useEndpointTranslation: needTranslation, diff --git a/src/rpc/actionChain/chainNode/core.ts b/src/rpc/actionChain/chainNode/core.ts index 18677b9..1767685 100644 --- a/src/rpc/actionChain/chainNode/core.ts +++ b/src/rpc/actionChain/chainNode/core.ts @@ -41,9 +41,7 @@ class CorePlugin extends ChainNodeBase { 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); }); } @@ -55,21 +53,14 @@ class CorePlugin extends ChainNodeBase { this.getProblems(needTranslation, function (e, problems) { if (e) return cb(e); keyword = Number(keyword) || keyword; - const metaFid = storageUtils.exist(keyword) - ? storageUtils.meta(keyword).id - : NaN; + const metaFid = storageUtils.exist(keyword) ? storageUtils.meta(keyword).id : NaN; const problem = problems.find(function (x) { if (keyword?.fid) { return x.fid + "" === keyword.fid + ""; } else if (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!"); diff --git a/src/rpc/actionChain/chainNode/leetcode.cn.ts b/src/rpc/actionChain/chainNode/leetcode.cn.ts index 71739d9..958cd0e 100644 --- a/src/rpc/actionChain/chainNode/leetcode.cn.ts +++ b/src/rpc/actionChain/chainNode/leetcode.cn.ts @@ -132,10 +132,7 @@ class LeetCodeCn extends ChainNodeBase { getUserContestP = (username, cb) => { 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.headers.Referer = configUtils.sys.urls.u.replace("$username", username); opts.json = true; opts.body = { @@ -181,14 +178,11 @@ class LeetCodeCn extends ChainNodeBase { getRatingOnline = (cb) => { const _request = request.defaults({ jar: true }); - _request( - "https://zerotrac.github.io/leetcode_problem_rating/data.json", - function (error: any, _, body: any) { - // console.log(error); - // console.log(info); - cb(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); + }); }; // eslint-disable-next-line @typescript-eslint/no-unused-vars @@ -207,12 +201,7 @@ class LeetCodeCn extends ChainNodeBase { } function signOpts(opts: any, user: any) { - opts.headers.Cookie = - "LEETCODE_SESSION=" + - user.sessionId + - ";csrftoken=" + - user.sessionCSRF + - ";"; + opts.headers.Cookie = "LEETCODE_SESSION=" + user.sessionId + ";csrftoken=" + user.sessionCSRF + ";"; opts.headers["X-CSRFToken"] = user.sessionCSRF; opts.headers["X-Requested-With"] = "XMLHttpRequest"; } diff --git a/src/rpc/actionChain/chainNode/leetcode.ts b/src/rpc/actionChain/chainNode/leetcode.ts index 4f983eb..c5e4084 100644 --- a/src/rpc/actionChain/chainNode/leetcode.ts +++ b/src/rpc/actionChain/chainNode/leetcode.ts @@ -30,12 +30,7 @@ class LeetCode extends ChainNodeBase { } signOpts(opts, user) { - opts.headers.Cookie = - "LEETCODE_SESSION=" + - user.sessionId + - ";csrftoken=" + - user.sessionCSRF + - ";"; + opts.headers.Cookie = "LEETCODE_SESSION=" + user.sessionId + ";csrftoken=" + user.sessionCSRF + ";"; opts.headers["X-CSRFToken"] = user.sessionCSRF; opts.headers["X-Requested-With"] = "XMLHttpRequest"; } @@ -87,9 +82,7 @@ class LeetCode extends ChainNodeBase { }; getCategoryProblems = (category, cb) => { - const opts = this.makeOpts( - configUtils.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) { @@ -111,10 +104,7 @@ class LeetCode extends ChainNodeBase { fid: p.stat.frontend_question_id, name: p.stat.question__title, slug: p.stat.question__title_slug, - link: configUtils.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: commUtils.getNameByLevel(p.difficulty.level), @@ -129,8 +119,7 @@ class LeetCode extends ChainNodeBase { getProblem = (problem, needTranslation, cb) => { const user = sessionUtils.getUser(); - if (problem.locked && !user.paid) - return cb("failed to load locked problem!"); + if (problem.locked && !user.paid) return cb("failed to load locked problem!"); const opts = this.makeOpts(configUtils.sys.urls.graphql); opts.headers.Origin = configUtils.sys.urls.base; @@ -170,10 +159,7 @@ class LeetCode extends ChainNodeBase { 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; @@ -289,9 +275,7 @@ class LeetCode extends ChainNodeBase { }; testProblem = (problem, cb) => { - const opts = this.makeOpts( - configUtils.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) { @@ -303,11 +287,7 @@ class LeetCode extends ChainNodeBase { if (task.interpret_expected_id) { tasks.push({ type: "Expected", id: task.interpret_expected_id }); } - const q = new Queue( - tasks, - { opts: opts, results: [] }, - that.verifyResult - ); + const q = new Queue(tasks, { opts: opts, results: [] }, that.verifyResult); q.run(null, function (e, ctx) { return cb(e, ctx.results); }); @@ -315,20 +295,14 @@ class LeetCode extends ChainNodeBase { }; submitProblem = (problem, cb) => { - const opts = this.makeOpts( - configUtils.sys.urls.submit.replace("$slug", problem.slug) - ); + 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 q = new Queue( - tasks, - { opts: opts, results: [] }, - that.verifyResult - ); + const q = new Queue(tasks, { opts: opts, results: [] }, that.verifyResult); q.run(null, function (e, ctx) { return cb(e, ctx.results); }); @@ -336,13 +310,8 @@ class LeetCode extends ChainNodeBase { }; getSubmissions = (problem, cb) => { - const opts = this.makeOpts( - configUtils.sys.urls.submissions.replace("$slug", problem.slug) - ); - opts.headers.Referer = configUtils.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); @@ -351,18 +320,14 @@ class LeetCode extends ChainNodeBase { // 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( - configUtils.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); @@ -379,9 +344,7 @@ class LeetCode extends ChainNodeBase { starProblem = (problem, starred, cb) => { const user = sessionUtils.getUser(); - const operationName = starred - ? "addQuestionToFavorite" - : "removeQuestionFromFavorite"; + 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; @@ -422,14 +385,7 @@ class LeetCode extends ChainNodeBase { opts.headers.Referer = configUtils.sys.urls.base; opts.json = true; opts.body = { - query: [ - "{", - " user {", - " username", - " isCurrentUserPremium", - " }", - "}", - ].join("\n"), + query: ["{", " user {", " username", " isCurrentUserPremium", " }", "}"].join("\n"), variables: {}, }; @@ -513,9 +469,7 @@ class LeetCode extends ChainNodeBase { 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; @@ -589,22 +543,16 @@ class LeetCode extends ChainNodeBase { const _request = request.defaults({ jar: true }); let that = this; _request(urls.github_login_request, function (_, __, body) { - const authenticityToken = body.match( - /name="authenticity_token" value="(.*?)"/ - ); + const authenticityToken = body.match(/name="authenticity_token" value="(.*?)"/); let gaId = body.match(/name="ga_id" value="(.*?)"/); if (!gaId) { gaId = ""; } let requiredField = body.match(/name="required_field_(.*?)"/); const timestamp = body.match(/name="timestamp" value="(.*?)"/); - const timestampSecret = body.match( - /name="timestamp_secret" value="(.*?)"/ - ); + const timestampSecret = body.match(/name="timestamp_secret" value="(.*?)"/); - if ( - !(authenticityToken && timestamp && timestampSecret && requiredField) - ) { + if (!(authenticityToken && timestamp && timestampSecret && requiredField)) { return cb("Get GitHub payload failed"); } requiredField = "required_field_" + requiredField[1]; @@ -648,9 +596,7 @@ class LeetCode extends ChainNodeBase { ], function (e, result) { if (e) return reply.info(e); - const authenticityTokenTwoFactor = body.match( - /name="authenticity_token" value="(.*?)"/ - ); + const authenticityTokenTwoFactor = body.match(/name="authenticity_token" value="(.*?)"/); if (authenticityTokenTwoFactor === null) { return cb("Get GitHub two-factor token failed"); } @@ -695,18 +641,10 @@ class LeetCode extends ChainNodeBase { if (resp.statusCode !== 200) { 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="(.*?)"/ - ); + 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"); } diff --git a/src/rpc/actionChain/chainNode/solution.discuss.ts b/src/rpc/actionChain/chainNode/solution.discuss.ts index a7d5def..35afd37 100644 --- a/src/rpc/actionChain/chainNode/solution.discuss.ts +++ b/src/rpc/actionChain/chainNode/solution.discuss.ts @@ -30,13 +30,8 @@ class SolutionDiscuss extends ChainNodeBase { 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"); + 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); @@ -104,8 +99,7 @@ function getSolution(problem, lang, cb) { }; request(opts, function (e, resp, body) { if (e) return cb(e); - if (resp.statusCode !== 200) - return cb({ msg: "http error", statusCode: resp.statusCode }); + 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; diff --git a/src/rpc/factory/api/cacheApi.ts b/src/rpc/factory/api/cacheApi.ts index 6ee082b..e164128 100644 --- a/src/rpc/factory/api/cacheApi.ts +++ b/src/rpc/factory/api/cacheApi.ts @@ -35,10 +35,7 @@ class CacheApi extends ApiBase { 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) - ); + return name.length === 0 || (isInteger ? f.name.startsWith(name + ".") : f.name === name); }); if (argv.delete) { diff --git a/src/rpc/factory/api/showApi.ts b/src/rpc/factory/api/showApi.ts index e6f0b75..3ef7823 100644 --- a/src/rpc/factory/api/showApi.ts +++ b/src/rpc/factory/api/showApi.ts @@ -99,18 +99,11 @@ class ShowApi extends ApiBase { } genFileName(problem, opts) { const path = require("path"); - const params = [ - storageUtils.fmt(configUtils.file.show, problem), - "", - storageUtils.getFileExtByLanguage(opts.lang), - ]; + 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, ".") - ); + const name = path.join(opts.outdir, params.join(".").replace(/\.+/g, ".")); if (!storageUtils.exist(name)) return name; params[1] = i; } @@ -182,8 +175,7 @@ class ShowApi extends ApiBase { 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.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}`); @@ -199,12 +191,10 @@ class ShowApi extends ApiBase { 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); - }); + chainMgr.getChainHead().getProblem(argv.keyword, !argv.dontTranslate, function (e, problem) { + if (e) return reply.info(e); + that.showProblem(problem, argv); + }); } else { // } diff --git a/src/rpc/factory/api/starApi.ts b/src/rpc/factory/api/starApi.ts index 0842962..69bdc7c 100644 --- a/src/rpc/factory/api/starApi.ts +++ b/src/rpc/factory/api/starApi.ts @@ -40,25 +40,15 @@ class StarApi extends ApiBase { 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().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 }); - }); + 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 }); }); + }); } } diff --git a/src/rpc/factory/api/submitApi.ts b/src/rpc/factory/api/submitApi.ts index 9a8d61b..2d796f8 100644 --- a/src/rpc/factory/api/submitApi.ts +++ b/src/rpc/factory/api/submitApi.ts @@ -59,8 +59,7 @@ class SubmitApi extends ApiBase { call(argv) { sessionUtils.argv = argv; - if (!storageUtils.exist(argv.filename)) - return reply.fatal("File " + argv.filename + " not exist!"); + if (!storageUtils.exist(argv.filename)) return reply.fatal("File " + argv.filename + " not exist!"); const meta = storageUtils.meta(argv.filename); let that = this; @@ -86,14 +85,7 @@ class SubmitApi extends ApiBase { 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 - ); + that.printLine(log_obj, result, "%d/%d cases passed (%s)", result.passed, result.total, result.runtime); if (result.ok) { sessionUtils.updateStat("ac", 1); diff --git a/src/rpc/factory/api/testApi.ts b/src/rpc/factory/api/testApi.ts index f6b3ea0..3f351c1 100644 --- a/src/rpc/factory/api/testApi.ts +++ b/src/rpc/factory/api/testApi.ts @@ -80,8 +80,7 @@ class TestApi extends ApiBase { runTest(argv) { let that = this; - if (!storageUtils.exist(argv.filename)) - return reply.fatal("File " + argv.filename + " not exist!"); + if (!storageUtils.exist(argv.filename)) return reply.fatal("File " + argv.filename + " not exist!"); const meta = storageUtils.meta(argv.filename); @@ -174,9 +173,7 @@ class TestApi extends ApiBase { if (results[1]) { results[0].expected_answer = results[1].answer; } - results[0].stdout = results[0].stdout - .slice(1, -1) - .replace(/\\n/g, "\n"); + 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); diff --git a/src/rpc/factory/api/userApi.ts b/src/rpc/factory/api/userApi.ts index 68c5b0f..ab9a3d7 100644 --- a/src/rpc/factory/api/userApi.ts +++ b/src/rpc/factory/api/userApi.ts @@ -89,8 +89,7 @@ class UserApi extends ApiBase { // 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?" })); + 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 @@ -112,13 +111,9 @@ class UserApi extends ApiBase { { name: "pass", required: true, hidden: true }, ], function (e, user) { - if (e) - return reply.info(JSON.stringify({ code: -4, msg: e.msg || e })); + 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 }) - ); + if (e) return reply.info(JSON.stringify({ code: -5, msg: e.msg || e })); reply.info(JSON.stringify({ code: 100, user_name: user.name })); }); } @@ -137,8 +132,7 @@ class UserApi extends ApiBase { 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 })); + if (e) return reply.info(JSON.stringify({ code: -6, msg: e.msg || e })); reply.info(JSON.stringify({ code: 100, user_name: user.name })); }); } @@ -148,10 +142,7 @@ class UserApi extends ApiBase { 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?" }) - ); + } else return reply.info(JSON.stringify({ code: -7, msg: "You are not login yet?" })); } } } diff --git a/src/rpc/utils/commUtils.ts b/src/rpc/utils/commUtils.ts index 401979d..d895b3c 100644 --- a/src/rpc/utils/commUtils.ts +++ b/src/rpc/utils/commUtils.ts @@ -41,8 +41,7 @@ class CommUtils { let bufs: Array = []; console.log( - "NOTE: to finish the input, press " + - (storageUtils.isWindows() ? " and " : "") + "NOTE: to finish the input, press " + (storageUtils.isWindows() ? " and " : "") ); stdin.on("readable", function () { diff --git a/src/rpc/utils/configUtils.ts b/src/rpc/utils/configUtils.ts index 7a9ce2c..6c829a9 100644 --- a/src/rpc/utils/configUtils.ts +++ b/src/rpc/utils/configUtils.ts @@ -49,10 +49,8 @@ class Config { 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", + 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", @@ -61,8 +59,7 @@ class Config { 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", + 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/", @@ -124,22 +121,18 @@ class Config { 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.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.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.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/"; } } diff --git a/src/rpc/utils/queueUtils.ts b/src/rpc/utils/queueUtils.ts index d969b41..3ff2496 100644 --- a/src/rpc/utils/queueUtils.ts +++ b/src/rpc/utils/queueUtils.ts @@ -50,8 +50,7 @@ export class Queue { 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; } diff --git a/src/rpc/utils/sessionUtils.ts b/src/rpc/utils/sessionUtils.ts index 01120ae..bd30d67 100644 --- a/src/rpc/utils/sessionUtils.ts +++ b/src/rpc/utils/sessionUtils.ts @@ -30,10 +30,7 @@ class Session { 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, - configUtils.autologin.enable ? [] : ["pass"] - ); + const _user = underscore.omit(user, configUtils.autologin.enable ? [] : ["pass"]); storageUtils.setCache(commUtils.KEYS.user, _user); }; diff --git a/src/rpc/utils/storageUtils.ts b/src/rpc/utils/storageUtils.ts index 5286cba..c8c1617 100644 --- a/src/rpc/utils/storageUtils.ts +++ b/src/rpc/utils/storageUtils.ts @@ -304,9 +304,7 @@ class StorageUtils { } public getData(fullpath) { - return fs.existsSync(fullpath) - ? fs.readFileSync(fullpath).toString() - : null; + return fs.existsSync(fullpath) ? fs.readFileSync(fullpath).toString() : null; } // 获取要提交测试的数据 @@ -333,9 +331,7 @@ class StorageUtils { */ 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() - ); + 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, ""); @@ -400,16 +396,7 @@ class StorageUtils { // 加载输出模板数据 public render(tpl, data) { - const tplfile = path.join( - __dirname, - "..", - "..", - "..", - "..", - "resources", - "templates", - tpl + ".tpl" - ); + 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"); diff --git a/src/service/BaseWebviewService.ts b/src/service/BaseWebviewService.ts index 02446e8..7345d28 100644 --- a/src/service/BaseWebviewService.ts +++ b/src/service/BaseWebviewService.ts @@ -7,15 +7,7 @@ * Copyright (c) 2022 ccagml . All rights reserved. */ -import { - commands, - ConfigurationChangeEvent, - Disposable, - ViewColumn, - WebviewPanel, - window, - workspace, -} from "vscode"; +import { commands, ConfigurationChangeEvent, Disposable, ViewColumn, WebviewPanel, window, workspace } from "vscode"; import { markdownService } from "./MarkdownService"; import { IWebViewOption } from "../model/Model"; import { openSettingsEditor } from "../utils/ConfigUtils"; @@ -48,25 +40,15 @@ export abstract class BaseWebViewService implements Disposable { } ); this.panel.onDidDispose(this.onDidDisposeWebview, this, this.listeners); - this.panel.webview.onDidReceiveMessage( - this.onDidReceiveMessage, - this, - this.listeners - ); - workspace.onDidChangeConfiguration( - this.onDidChangeConfiguration, - 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); - }); + commands.executeCommand("workbench.action.focusSecondEditorGroup").then(() => { + this.panel!.reveal(viewColumn, preserveFocus); + }); } else { this.panel.reveal(viewColumn, preserveFocus); } @@ -83,9 +65,7 @@ export abstract class BaseWebViewService implements Disposable { this.listeners = []; } - protected async onDidChangeConfiguration( - event: ConfigurationChangeEvent - ): Promise { + protected async onDidChangeConfiguration(event: ConfigurationChangeEvent): Promise { if (this.panel && event.affectsConfiguration("markdown")) { this.panel.webview.html = this.getWebviewContent(); } diff --git a/src/service/ExecuteService.ts b/src/service/ExecuteService.ts index 6b2de70..5becaba 100644 --- a/src/service/ExecuteService.ts +++ b/src/service/ExecuteService.ts @@ -12,20 +12,8 @@ import * as fse from "fs-extra"; import * as os from "os"; import * as path from "path"; import { ExtensionContext } from "vscode"; -import { - ConfigurationChangeEvent, - Disposable, - MessageItem, - window, - workspace, -} from "vscode"; -import { - DialogOptions, - DialogType, - Endpoint, - IProblem, - leetcodeHasInited, -} from "../model/Model"; +import { ConfigurationChangeEvent, Disposable, MessageItem, window, workspace } from "vscode"; +import { DialogOptions, DialogType, Endpoint, IProblem, leetcodeHasInited } from "../model/Model"; import { executeCommand, executeCommandWithProgress } from "../utils/CliUtils"; import { getNodePath } from "../utils/ConfigUtils"; import { openUrl, promptForOpenOutputChannel } from "../utils/OutputUtils"; @@ -41,32 +29,15 @@ class ExecuteService implements Disposable { constructor() { // this.leetCodeCliResourcesRootPath = path.join(__dirname, "..", "..", "node_modules", "rpc"); if (!systemUtils.useVscodeNode()) { - this.leetCodeCliResourcesRootPath = path.join( - __dirname, - "..", - "..", - "..", - "resources" - ); + this.leetCodeCliResourcesRootPath = path.join(__dirname, "..", "..", "..", "resources"); } - this.leetCodeCliRootPath = path.join( - __dirname, - "..", - "..", - "..", - "out", - "src", - "rpc" - ); + 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 - ); + this.configurationChangeListener = workspace.onDidChangeConfiguration((event: ConfigurationChangeEvent) => { + if (event.affectsConfiguration("leetcode-problem-rating.nodePath")) { + this.nodeExecutable = this.initNodePath(); + } + }, this); } public async getLeetCodeBinaryPath(): Promise { @@ -74,29 +45,20 @@ class ExecuteService implements Disposable { return `${path.join(this.leetCodeCliRootPath, "childMain.js")}`; } else { if (systemUtils.useWsl()) { - return `${await systemUtils.toWslPath( - `"${path.join(this.leetCodeCliResourcesRootPath, "bin", "leetcode")}"` - )}`; + return `${await systemUtils.toWslPath(`"${path.join(this.leetCodeCliResourcesRootPath, "bin", "leetcode")}"`)}`; } - return `"${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); + 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}` - ); + 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}"`; @@ -122,38 +84,21 @@ class ExecuteService implements Disposable { public async deleteCache() { try { - await this.executeCommandEx(this.nodeExecutable, [ - await this.getLeetCodeBinaryPath(), - "cache", - "-d", - ]); + await this.executeCommandEx(this.nodeExecutable, [await this.getLeetCodeBinaryPath(), "cache", "-d"]); } catch (error) { - await promptForOpenOutputChannel( - "Failed to delete cache. 请查看控制台信息~", - DialogType.error - ); + await promptForOpenOutputChannel("Failed to delete cache. 请查看控制台信息~", DialogType.error); } } public async getUserInfo(): Promise { - return await this.executeCommandEx(this.nodeExecutable, [ - await this.getLeetCodeBinaryPath(), - "user", - ]); + return await this.executeCommandEx(this.nodeExecutable, [await this.getLeetCodeBinaryPath(), "user"]); } public async signOut(): Promise { - return await this.executeCommandEx(this.nodeExecutable, [ - await this.getLeetCodeBinaryPath(), - "user", - "-L", - ]); + return await this.executeCommandEx(this.nodeExecutable, [await this.getLeetCodeBinaryPath(), "user", "-L"]); } - public async listProblems( - showLocked: boolean, - needTranslation: boolean - ): Promise { + 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 @@ -173,14 +118,7 @@ class ExecuteService implements Disposable { needTranslation: boolean ): Promise { const templateType: string = showDescriptionInComment ? "-cx" : "-c"; - const cmd: string[] = [ - await this.getLeetCodeBinaryPath(), - "show", - problemNode.qid, - templateType, - "-l", - language, - ]; + const cmd: string[] = [await this.getLeetCodeBinaryPath(), "show", problemNode.qid, templateType, "-l", language]; if (!needTranslation) { cmd.push("-T"); // use -T to force English version @@ -197,20 +135,9 @@ class ExecuteService implements Disposable { } } - public async showSolution( - input: string, - language: string, - needTranslation: boolean - ): Promise { + 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, - ]; + const cmd: string[] = [await this.getLeetCodeBinaryPath(), "show", input, "--solution", "-l", language]; if (!needTranslation) { cmd.push("-T"); } @@ -222,17 +149,9 @@ class ExecuteService implements Disposable { return solution; } - public async getUserContest( - needTranslation: boolean, - username: string - ): Promise { + public async getUserContest(needTranslation: boolean, username: string): Promise { // solution don't support translation - const cmd: string[] = [ - await this.getLeetCodeBinaryPath(), - "query", - "-b", - username, - ]; + const cmd: string[] = [await this.getLeetCodeBinaryPath(), "query", "-b", username]; if (!needTranslation) { cmd.push("-T"); } @@ -257,17 +176,8 @@ class ExecuteService implements Disposable { 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 - ); + const cmd: string[] = [await this.getLeetCodeBinaryPath(), "query", "-z", username]; + const solution: string = await this.executeCommandWithProgressEx("Fetching testapi...", this.nodeExecutable, cmd); return solution; } @@ -285,40 +195,28 @@ class ExecuteService implements Disposable { return solution; } - public async getDescription( - problemNodeId: string, - needTranslation: boolean - ): Promise { - const cmd: string[] = [ - await this.getLeetCodeBinaryPath(), - "show", - problemNodeId, - "-x", - ]; + 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 - ); + 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}`, + ]); } - 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; @@ -327,63 +225,53 @@ class ExecuteService implements Disposable { } } - public async testSolution( - filePath: string, - testString?: string, - allCase?: boolean - ): Promise { + 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, - [ + return await this.executeCommandWithProgressEx("Submitting to LeetCode...", this.nodeExecutable, [ await this.getLeetCodeBinaryPath(), "test", - `"${filePath}"`, + `${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", + ]); } - 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( - "Submitting to LeetCode...", - this.nodeExecutable, - [await this.getLeetCodeBinaryPath(), "test", `"${filePath}"`] - ); + return await this.executeCommandWithProgressEx("Submitting to LeetCode...", this.nodeExecutable, [ + await this.getLeetCodeBinaryPath(), + "test", + `"${filePath}"`, + ]); } public async switchEndpoint(endpoint: string): Promise { @@ -406,23 +294,12 @@ class ExecuteService implements Disposable { } } - public async toggleFavorite( - node: IProblem, - addToFavorite: boolean - ): Promise { - const commandParams: string[] = [ - await this.getLeetCodeBinaryPath(), - "star", - node.id, - ]; + 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 - ); + await this.executeCommandWithProgressEx("Updating the favorite list...", "node", commandParams); } public get node(): string { @@ -458,12 +335,7 @@ class ExecuteService implements Disposable { options: cp.SpawnOptions = { shell: true } ): Promise { if (systemUtils.useWsl()) { - return await executeCommandWithProgress( - message, - "wsl", - [command].concat(args), - options - ); + return await executeCommandWithProgress(message, "wsl", [command].concat(args), options); } return await executeCommandWithProgress(message, command, args, options); } diff --git a/src/service/FileButtonService.ts b/src/service/FileButtonService.ts index 134a97c..875d308 100644 --- a/src/service/FileButtonService.ts +++ b/src/service/FileButtonService.ts @@ -13,8 +13,7 @@ import { NodeModel } from "../model/NodeModel"; import { getEditorShortcuts } from "../utils/ConfigUtils"; export class FileButtonService implements vscode.CodeLensProvider { - private onDidChangeCodeLensesEmitter: vscode.EventEmitter = - new vscode.EventEmitter(); + private onDidChangeCodeLensesEmitter: vscode.EventEmitter = new vscode.EventEmitter(); get onDidChangeCodeLenses(): vscode.Event { return this.onDidChangeCodeLensesEmitter.event; @@ -32,12 +31,7 @@ export class FileButtonService implements vscode.CodeLensProvider { return temp_result; } - const range: vscode.Range = new vscode.Range( - codeLensLine, - 0, - codeLensLine, - 0 - ); + const range: vscode.Range = new vscode.Range(codeLensLine, 0, codeLensLine, 0); if (shortcuts.indexOf("submit") >= 0) { temp_result.push( @@ -82,9 +76,7 @@ export class FileButtonService implements vscode.CodeLensProvider { temp_result.push( new vscode.CodeLens(range, { title: node.isFavorite ? "Unstar" : "Star", - command: node.isFavorite - ? "leetcode.removeFavorite" - : "leetcode.addFavorite", + command: node.isFavorite ? "leetcode.removeFavorite" : "leetcode.addFavorite", arguments: [node], }) ); @@ -116,12 +108,7 @@ export class FileButtonService implements vscode.CodeLensProvider { * createCase */ public createCase(codeLensLine, document, testCase) { - const range: vscode.Range = new vscode.Range( - codeLensLine, - 0, - codeLensLine, - 0 - ); + const range: vscode.Range = new vscode.Range(codeLensLine, 0, codeLensLine, 0); return new vscode.CodeLens(range, { title: "case", @@ -150,13 +137,9 @@ export class FileButtonService implements vscode.CodeLensProvider { typescript: "//", }; - public provideCodeLenses( - document: vscode.TextDocument - ): vscode.ProviderResult { + public provideCodeLenses(document: vscode.TextDocument): vscode.ProviderResult { const content: string = document.getText(); - const matchResult: RegExpMatchArray | null = content.match( - /@lc app=.* id=(.*) lang=.*/ - ); + const matchResult: RegExpMatchArray | null = content.match(/@lc app=.* id=(.*) lang=.*/); if (!matchResult) { return undefined; } @@ -172,17 +155,11 @@ export class FileButtonService implements vscode.CodeLensProvider { 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) - ); + 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, ""); + curCase += lineContent.replace(/#/g, "").replace(/\/\//g, "").replace(/--/g, "").replace(/\s+/g, ""); } // 收集所有用例 if (lineContent.indexOf("@lcpr case=start") >= 0) { diff --git a/src/service/MarkdownService.ts b/src/service/MarkdownService.ts index c0190c2..13c75df 100644 --- a/src/service/MarkdownService.ts +++ b/src/service/MarkdownService.ts @@ -22,14 +22,11 @@ class MarkdownService implements vscode.Disposable { public constructor() { this.reload(); - this.listener = vscode.workspace.onDidChangeConfiguration( - (event: vscode.ConfigurationChangeEvent) => { - if (event.affectsConfiguration("markdown")) { - this.reload(); - } - }, - this - ); + this.listener = vscode.workspace.onDidChangeConfiguration((event: vscode.ConfigurationChangeEvent) => { + if (event.affectsConfiguration("markdown")) { + this.reload(); + } + }, this); } public get localResourceRoots(): vscode.Uri[] { @@ -56,25 +53,19 @@ class MarkdownService implements vscode.Disposable { private getBuiltinStyles(): string { let styles: vscode.Uri[] = []; try { - const stylePaths: string[] = require(path.join( - this.config.extRoot, - "package.json" - ))["contributes"]["markdown.previewStyles"]; + 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." - ); + logOutput.appendLine("[Error] Fail to load built-in markdown style file."); } return styles - .map( - (style: vscode.Uri) => - `` - ) + .map((style: vscode.Uri) => ``) .join(os.EOL); } @@ -82,19 +73,9 @@ class MarkdownService implements vscode.Disposable { return [ ``, ].join(os.EOL); @@ -142,10 +123,7 @@ class MarkdownService implements vscode.Disposable { 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 - ); + const highlighted: string = options.highlight(tokens[idx].content, env.lang); return [ `
`,
         highlighted || md.utils.escapeHtml(tokens[idx].content),
@@ -158,9 +136,7 @@ class MarkdownService implements vscode.Disposable {
     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"
-      );
+      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]}`;
       }
@@ -185,30 +161,16 @@ class MarkdownConfiguration {
   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)
-    );
+    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
-    ) {
+    if (isWindows() && fontFamily === config.inspect("preview.fontFamily")!.defaultValue) {
       fontFamily = `${fontFamily}, 'Microsoft Yahei UI'`;
     }
     return fontFamily;
diff --git a/src/service/PreviewService.ts b/src/service/PreviewService.ts
index d997cfd..dd872bd 100644
--- a/src/service/PreviewService.ts
+++ b/src/service/PreviewService.ts
@@ -23,11 +23,7 @@ class PreviewService extends BaseWebViewService {
     return this.sideMode;
   }
 
-  public show(
-    descString: string,
-    node: IProblem,
-    isSideMode: boolean = false
-  ): void {
+  public show(descString: string, node: IProblem, isSideMode: boolean = false): void {
     this.description = this.parseDescription(descString, node);
     this.node = node;
     this.sideMode = isSideMode;
@@ -80,8 +76,7 @@ class PreviewService extends BaseWebViewService {
                 }
                 `,
     };
-    const { title, url, category, difficulty, likes, dislikes, body } =
-      this.description;
+    const { title, url, category, difficulty, likes, dislikes, body } = this.description;
     const head: string = markdownService.render(`# [${title}](${url})`);
     const info: string = markdownService.render(
       [
@@ -94,24 +89,18 @@ class PreviewService extends BaseWebViewService {
       `
`, `Tags`, markdownService.render( - this.description.tags - .map((t: string) => `[\`${t}\`](https://leetcode.com/tag/${t})`) - .join(" | ") + 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(" | ") - ), + 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)})` + `[Discussion](${this.getDiscussionLink(url)}) | [Solution](${this.getSolutionLink(url)})` ); return ` @@ -161,10 +150,7 @@ class PreviewService extends BaseWebViewService { // await commands.executeCommand("workbench.action.toggleSidebarVisibility"); // } - private parseDescription( - descString: string, - problem: IProblem - ): IDescription { + private parseDescription(descString: string, problem: IProblem): IDescription { const [ , , @@ -193,12 +179,7 @@ class PreviewService extends BaseWebViewService { 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
" - ), + body: body.join("\n").replace(/
[\r\n]*([^]+?)[\r\n]*<\/pre>/g, "
$1
"), }; } @@ -207,10 +188,7 @@ class PreviewService extends BaseWebViewService { 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 url.replace("/description/", "/discuss/?currentPage=1&orderBy=most_votes&query="); } return "https://leetcode.com"; diff --git a/src/service/StatusBarService.ts b/src/service/StatusBarService.ts index df40be3..5d379b8 100644 --- a/src/service/StatusBarService.ts +++ b/src/service/StatusBarService.ts @@ -7,13 +7,7 @@ * Copyright (c) 2022 ccagml . All rights reserved. */ -import { - ConfigurationChangeEvent, - Disposable, - workspace, - StatusBarItem, - window, -} from "vscode"; +import { ConfigurationChangeEvent, Disposable, workspace, StatusBarItem, window } from "vscode"; import { UserStatus, userContestRanKingBase } from "../model/Model"; import { enableStatusBar } from "../utils/ConfigUtils"; import { eventService } from "./EventService"; @@ -83,16 +77,11 @@ class StatusBarService implements Disposable { this.currentUser = undefined; this.userStatus = UserStatus.SignedOut; - this.configurationChangeListener = workspace.onDidChangeConfiguration( - (event: ConfigurationChangeEvent) => { - if ( - event.affectsConfiguration("leetcode-problem-rating.enableStatusBar") - ) { - this.setStatusBarVisibility(); - } - }, - this - ); + this.configurationChangeListener = workspace.onDidChangeConfiguration((event: ConfigurationChangeEvent) => { + if (event.affectsConfiguration("leetcode-problem-rating.enableStatusBar")) { + this.setStatusBarVisibility(); + } + }, this); } // 更新状态栏的数据 @@ -104,11 +93,9 @@ class StatusBarService implements Disposable { switch (status) { case UserStatus.SignedIn: if (UserContestInfo && UserContestInfo.attendedContestsCount > 0) { - this.instance.text = `用户: ${user}, 积分: ${Math.floor( - UserContestInfo.rating - )}, 名次: ${UserContestInfo.localRanking} / ${ - UserContestInfo.localTotalParticipants - } (${UserContestInfo.topPercentage}%), 全部名次: ${ + this.instance.text = `用户: ${user}, 积分: ${Math.floor(UserContestInfo.rating)}, 名次: ${ + UserContestInfo.localRanking + } / ${UserContestInfo.localTotalParticipants} (${UserContestInfo.topPercentage}%), 全部名次: ${ UserContestInfo.globalRanking } / ${UserContestInfo.globalTotalParticipants}`; } else { @@ -126,19 +113,13 @@ class StatusBarService implements Disposable { this.userStatus = status; this.currentUser = user; } - public update_UserContestInfo( - UserContestInfo?: userContestRanKingBase | undefined - ) { + public update_UserContestInfo(UserContestInfo?: userContestRanKingBase | undefined) { this.currentUserContestInfo = UserContestInfo; } // 更新数据 public update(): void { - this.update_instance( - this.userStatus, - this.currentUser, - this.currentUserContestInfo - ); + this.update_instance(this.userStatus, this.currentUser, this.currentUserContestInfo); } //销毁数据 diff --git a/src/service/SubmissionService.ts b/src/service/SubmissionService.ts index 146caed..9d596d1 100644 --- a/src/service/SubmissionService.ts +++ b/src/service/SubmissionService.ts @@ -37,17 +37,11 @@ class SubmissionService extends BaseWebViewService { 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 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") - ); + .map((key: string) => [`### ${key}`, "```", this.result[key].join("\n"), "```"].join("\n")); + const body: string = markdownService.render([title, ...messages, ...sections].join("\n")); return ` @@ -79,10 +73,7 @@ class SubmissionService extends BaseWebViewService { } private async openKeybindingsEditor(query?: string): Promise { - await commands.executeCommand( - "workbench.action.openGlobalKeybindings", - query - ); + await commands.executeCommand("workbench.action.openGlobalKeybindings", query); } private parseResult(raw: string): IResult { diff --git a/src/service/TreeDataService.ts b/src/service/TreeDataService.ts index b1b4d01..9eab305 100644 --- a/src/service/TreeDataService.ts +++ b/src/service/TreeDataService.ts @@ -30,12 +30,11 @@ import { promptForOpenOutputChannel } from "../utils/OutputUtils"; export class TreeDataService implements vscode.TreeDataProvider { private context: vscode.ExtensionContext; - private onDidChangeTreeDataEvent: vscode.EventEmitter< + private onDidChangeTreeDataEvent: vscode.EventEmitter = new vscode.EventEmitter< NodeModel | undefined | null - > = new vscode.EventEmitter(); + >(); // tslint:disable-next-line:member-ordering - public readonly onDidChangeTreeData: vscode.Event = - this.onDidChangeTreeDataEvent.event; + public readonly onDidChangeTreeData: vscode.Event = this.onDidChangeTreeDataEvent.event; public initialize(context: vscode.ExtensionContext): void { this.context = context; @@ -55,9 +54,7 @@ export class TreeDataService implements vscode.TreeDataProvider { await treeViewController.refreshCheck(); } - public getTreeItem( - element: NodeModel - ): vscode.TreeItem | Thenable { + public getTreeItem(element: NodeModel): vscode.TreeItem | Thenable { if (element.id === "notSignIn") { return { label: element.name, @@ -78,8 +75,7 @@ export class TreeDataService implements vscode.TreeDataProvider { const result: vscode.TreeItem | Thenable = { label: element.isProblem - ? (element.score > "0" ? "[score:" + element.score + "]" : "") + - `ID:${element.id}.${element.name} ` + ? (element.score > "0" ? "[score:" + element.score + "]" : "") + `ID:${element.id}.${element.name} ` : element.name, tooltip: this.getSubCategoryTooltip(element), collapsibleState: element.isProblem @@ -93,9 +89,7 @@ export class TreeDataService implements vscode.TreeDataProvider { return result; } - public getChildren( - element?: NodeModel | undefined - ): vscode.ProviderResult { + public getChildren(element?: NodeModel | undefined): vscode.ProviderResult { if (!statusBarService.getUser()) { return [ new NodeModel( @@ -195,9 +189,7 @@ export class TreeDataService implements vscode.TreeDataProvider { 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", "lock.png")); } return this.context.asAbsolutePath(path.join("resources", "blank.png")); default: diff --git a/src/service/TreeItemDecorationService.ts b/src/service/TreeItemDecorationService.ts index 8c3b8d7..cc87975 100644 --- a/src/service/TreeItemDecorationService.ts +++ b/src/service/TreeItemDecorationService.ts @@ -84,12 +84,9 @@ export class TreeItemDecorationService implements FileDecorationProvider { } private isDifficultyBadgeEnabled(): boolean { - const configuration: WorkspaceConfiguration = workspace.getConfiguration( - "leetcode-problem-rating" - ); + const configuration: WorkspaceConfiguration = workspace.getConfiguration("leetcode-problem-rating"); return configuration.get("colorizeProblems", false); } } -export const treeItemDecorationService: TreeItemDecorationService = - new TreeItemDecorationService(); +export const treeItemDecorationService: TreeItemDecorationService = new TreeItemDecorationService(); diff --git a/src/utils/CliUtils.ts b/src/utils/CliUtils.ts index 2ad4cff..ffce86d 100644 --- a/src/utils/CliUtils.ts +++ b/src/utils/CliUtils.ts @@ -21,66 +21,55 @@ export async function executeCommand( 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(), - }); + 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]); } - - childProc.stdout?.on("data", (data: string | Buffer) => { - data = data.toString(); - result = result.concat(data); - logOutput.append(data); + 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) => { - 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("error", reject); + + 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( @@ -93,20 +82,15 @@ export async function executeCommandWithProgress( 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 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; diff --git a/src/utils/ConfigUtils.ts b/src/utils/ConfigUtils.ts index 93fbd98..ab38915 100644 --- a/src/utils/ConfigUtils.ts +++ b/src/utils/ConfigUtils.ts @@ -8,12 +8,7 @@ */ import { workspace, WorkspaceConfiguration, commands } from "vscode"; -import { - DescriptionConfiguration, - Endpoint, - IProblem, - SortingStrategy, -} from "../model/Model"; +import { DescriptionConfiguration, Endpoint, IProblem, SortingStrategy } from "../model/Model"; // vscode的配置 export function getVsCodeConfig(): WorkspaceConfiguration { @@ -26,14 +21,8 @@ export function isHideSolvedProblem(): boolean { } // 隐藏分数 -export function isHideScoreProblem( - problem: IProblem, - user_score: number -): boolean { - const config_value: string = getVsCodeConfig().get( - "hideScore", - "None" - ); +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; @@ -78,20 +67,17 @@ export function getWorkspaceFolder(): string { // 快捷操作 export function getEditorShortcuts(): string[] { - return getVsCodeConfig().get("editor.shortcuts", [ + 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", ]); -} - -export function isStarShortcut(): boolean { - const shortcuts: string[] = getVsCodeConfig().get( - "editor.shortcuts", - ["submit", "case", "allcase", "test", "solution"] - ); return shortcuts.indexOf("star") >= 0; } @@ -106,10 +92,7 @@ export function enableStatusBar(): boolean { // 展示方式 export function getDescriptionConfiguration(): IDescriptionConfiguration { - const setting: string = getVsCodeConfig().get( - "showDescription", - DescriptionConfiguration.InWebView - ); + const setting: string = getVsCodeConfig().get("showDescription", DescriptionConfiguration.InWebView); const config: IDescriptionConfiguration = { showInComment: false, showInWebview: true, @@ -167,10 +150,7 @@ export function isUseWsl() { } 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) { diff --git a/src/utils/OutputUtils.ts b/src/utils/OutputUtils.ts index 38788ba..f957381 100644 --- a/src/utils/OutputUtils.ts +++ b/src/utils/OutputUtils.ts @@ -23,12 +23,11 @@ export async function promptHintMessage( ): Promise { if (getVsCodeConfig().get(config)) { const choiceNoShowAgain: string = "Don't show again"; - const choice: string | undefined = - await vscode.window.showInformationMessage( - message, - choiceConfirm, - choiceNoShowAgain - ); + const choice: string | undefined = await vscode.window.showInformationMessage( + message, + choiceConfirm, + choiceNoShowAgain + ); if (choice === choiceConfirm) { await onConfirm(); } else if (choice === choiceNoShowAgain) { @@ -38,13 +37,12 @@ export async function promptHintMessage( } 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 - ); + 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"); @@ -61,32 +59,17 @@ export async function promptForSignIn(): Promise { } } -export async function promptForOpenOutputChannel( - message: string, - type: DialogType -): Promise { +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 - ); + result = await vscode.window.showInformationMessage(message, DialogOptions.open, DialogOptions.no); break; case DialogType.warning: - result = await vscode.window.showWarningMessage( - message, - DialogOptions.open, - DialogOptions.no - ); + result = await vscode.window.showWarningMessage(message, DialogOptions.open, DialogOptions.no); break; case DialogType.error: - result = await vscode.window.showErrorMessage( - message, - DialogOptions.open, - DialogOptions.no - ); + result = await vscode.window.showErrorMessage(message, DialogOptions.open, DialogOptions.no); break; default: break; @@ -98,8 +81,7 @@ export async function promptForOpenOutputChannel( } class LogOutput implements vscode.Disposable { - private readonly channel: vscode.OutputChannel = - vscode.window.createOutputChannel("LeetCodeProblemRating"); + private readonly channel: vscode.OutputChannel = vscode.window.createOutputChannel("LeetCodeProblemRating"); private LCPTCTX = {}; public appendLine(message: string): void { diff --git a/src/utils/SystemUtils.ts b/src/utils/SystemUtils.ts index 3162f98..962088d 100644 --- a/src/utils/SystemUtils.ts +++ b/src/utils/SystemUtils.ts @@ -29,25 +29,14 @@ export function useWsl(): boolean { } 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) + (await executeCommand("wsl", ["wslpath", "-w", `"${path.replace(/\\/g, "/").substr(0, 6)}"`])).trim() + + path.substr(7) ); } return (await executeCommand("wsl", ["wslpath", "-w", "/"])).trim() + path; @@ -70,8 +59,7 @@ export function genFileName(node: IProblem, language: string): string { 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=(.+?) /); + const matchResults: RegExpMatchArray | null = fileContent.match(/@lc.+id=(.+?) /); if (matchResults && matchResults.length === 2) { id = matchResults[1]; } From f7a19429d9ce8820265267decf1d23613f7f7fe6 Mon Sep 17 00:00:00 2001 From: ccagml Date: Fri, 18 Nov 2022 17:09:35 +0800 Subject: [PATCH 22/26] update --- src/rpc/utils/storageUtils.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/rpc/utils/storageUtils.ts b/src/rpc/utils/storageUtils.ts index c8c1617..f11dbf2 100644 --- a/src/rpc/utils/storageUtils.ts +++ b/src/rpc/utils/storageUtils.ts @@ -341,7 +341,7 @@ class StorageUtils { let temp_collect = ""; for (let all_input = 0; all_input < input.length; all_input++) { const element = input[all_input]; - let check_index = element.indexOf("输入"); + let check_index = element.indexOf("输入:"); if (check_index == -1) { check_index = element.indexOf("Input:"); } @@ -350,8 +350,7 @@ class StorageUtils { start_flag = true; continue; } - - check_index = element.indexOf("输出"); + check_index = element.indexOf("输出:"); if (check_index == -1) { check_index = element.indexOf("Output:"); } From 8b080f10e73a58a2fd656ea820d2097d59b18722 Mon Sep 17 00:00:00 2001 From: ccagml Date: Fri, 18 Nov 2022 17:20:36 +0800 Subject: [PATCH 23/26] update --- CHANGELOG.md | 3 ++- README.md | 38 ++++++++++++++++++++++++++------------ 2 files changed, 28 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b1c1fb8..953f0d6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,8 @@ -## version 2.0.1 +## version 2.1.0 - 重构工厂模式、责任链模式 - 去除多余模块 +- 增加所有测试用例单个提交的按钮,可以自己填写测试用例 ## version 2.0.0 diff --git a/README.md b/README.md index 1773069..4723698 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,7 @@ - 增加一键提交全部题目测试用例功能 - 尝试不需要额外安装 node 环境,使用 vscode 自带的 node 版本 - 从[zerotrac.github.io](https://zerotrac.github.io/leetcode_problem_rating/data.json)获取数据进行缓存,数据更新时,可以尝试使用 deleteAllCache,重新获取数据 +- 将所有提供的测试用例单独存放到代码下方,一键提交也会收集这部分的测试用例(简单去重()) # 关于本项目 @@ -42,25 +43,38 @@ ![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/) From ebb9004e6798dc39f1ba901cf24daaca578c26af Mon Sep 17 00:00:00 2001 From: ccagml Date: Fri, 18 Nov 2022 17:22:39 +0800 Subject: [PATCH 24/26] update --- package-lock.json | 16 ++++++++-------- package.json | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/package-lock.json b/package-lock.json index e8f44b6..38f039a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "vscode-leetcode-problem-rating", - "version": "2.0.1", + "version": "2.1.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "vscode-leetcode-problem-rating", - "version": "2.0.1", + "version": "2.1.0", "license": "MIT", "dependencies": { "ansi-styles": "3.2.1", @@ -1498,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" @@ -4158,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" diff --git a/package.json b/package.json index d6b30dd..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.1", + "version": "2.1.0", "author": "ccagml", "publisher": "ccagml", "license": "MIT", From 3dddce93b9a3ddc5748b0ca1b64f429350beb150 Mon Sep 17 00:00:00 2001 From: ccagml Date: Fri, 18 Nov 2022 17:26:45 +0800 Subject: [PATCH 25/26] update --- src/rpc/utils/storageUtils.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/rpc/utils/storageUtils.ts b/src/rpc/utils/storageUtils.ts index f11dbf2..19ac433 100644 --- a/src/rpc/utils/storageUtils.ts +++ b/src/rpc/utils/storageUtils.ts @@ -342,6 +342,11 @@ class StorageUtils { 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:"); } @@ -351,6 +356,9 @@ class StorageUtils { continue; } check_index = element.indexOf("输出:"); + if (check_index == -1) { + check_index = element.indexOf("输出:"); + } if (check_index == -1) { check_index = element.indexOf("Output:"); } From ccb8747c1ba9b885ac0d37e7c1b6df7e63742ddc Mon Sep 17 00:00:00 2001 From: ccagml Date: Fri, 18 Nov 2022 17:28:36 +0800 Subject: [PATCH 26/26] update --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 953f0d6..0751c9e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ - 重构工厂模式、责任链模式 - 去除多余模块 - 增加所有测试用例单个提交的按钮,可以自己填写测试用例 +- 修改部分题目一键用例问题 ## version 2.0.0