Skip to content

Commit 3ddd7c6

Browse files
committed
feat: hot100合并代码
1 parent 4a240e8 commit 3ddd7c6

20 files changed

+293
-139
lines changed

TO-DO.md

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
- [ ] commit到leetcode
1616
- [ ] 插件制作-WS/VS code
1717
- [ ] fork脚本的编写
18+
- [ ] 一键拉取题目集合,比如说hot 100
1819

1920
### 优先级中
2021

bin/lc.js

+56-82
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,38 @@
11
#! /usr/bin/env node
2-
import path from 'node:path'
3-
import { program } from 'commander'
4-
import { artFontLogo } from '#resources/text/art-font-logo.js'
5-
import { lcExamples } from '#resources/text/examples.js'
6-
import { love } from '#resources/text/love.js'
7-
import { aim } from '#resources/text/aim.js'
8-
import { referMode } from '#common/utils/create-check/refer-mode.js'
9-
import { getArgs } from '#common/utils/create-check/get-args.js'
10-
import { getQuestionToday } from '#common/utils/question-getter/getQuestionToday.js'
11-
import { createQuestion } from '#common/utils/question-handler/createQuestion.js'
12-
import { getQuestionFileName } from '#common/utils/question-handler/getQuestionFileName.js'
13-
import { createQuestionCopy } from '#common/utils/question-handler/createQuestionCopy.js'
14-
import { getQuestionRandom } from '#common/utils/question-getter/getQuestionRandom.js'
15-
import { getQuestionById } from '#common/utils/question-getter/getQuestionById.js'
16-
import { setQuestion } from '#common/utils/store/controller/question.js'
17-
import { getQuestionChineseName } from '#common/utils/question-handler/getQuestionChineseName.js'
18-
import { easyCreateView } from '#common/view/create.view.js'
19-
import { description } from '#resources/text/description.js'
20-
import { easyUpdateView } from '#common/view/update.view.js'
21-
import { getQuestionLanguage } from '#common/utils/question-handler/questionLanguage.js'
22-
import { easyLanguageView } from '#common/view/language.view.js'
23-
import { DefaultVer } from '#common/constants/question.const.js'
2+
import {program} from "commander";
3+
import {artFontLogo} from "#resources/text/art-font-logo.js";
4+
import {lcExamples} from "#resources/text/examples.js";
5+
import {love} from "#resources/text/love.js";
6+
import {aim} from "#resources/text/aim.js";
7+
import {referMode} from "#common/utils/create-check/refer-mode.js";
8+
import {getArgs} from "#common/utils/create-check/get-args.js";
9+
import {getQuestionToday} from "#common/utils/question-getter/getQuestionToday.js";
10+
import path from "path";
2411

25-
const version = process.env.VERSION ?? DefaultVer
12+
import {getQuestionRandom} from "#common/utils/question-getter/getQuestionRandom.js";
13+
14+
import {easyCreateView} from "#common/view/create.view.js";
15+
import {description} from "#resources/text/description.js";
16+
import {easyUpdateView} from "#common/view/update.view.js";
17+
import {getQuestionLanguage} from "#common/utils/question-handler/questionLanguage.js";
18+
import {easyLanguageView} from "#common/view/language.view.js";
19+
import {DefaultVer} from "#common/constants/question.const.js";
20+
import { create, createQuestionById } from "#common/utils/create-check/createUtil.js";
21+
22+
const version = process.env.VERSION??DefaultVer;
2623
program
27-
.version(version)
28-
.description(`${description}\n${artFontLogo}\n${aim}`)
29-
.addHelpText('after', lcExamples + love)
30-
.arguments('[identity]')
31-
.option('-t, --today', 'Get a question today.')
32-
.option('-i, --identity <identity>', 'Specify a question by identity.')
33-
.option('-r, --random', 'Get a question randomly.')
34-
.option('-e, --easy', 'Use easy mode.')
35-
.option('-d, --directory <directory>', 'Set the question directory.')
36-
.option('-l, --language [language]', 'Set/Get the code language of question.')
37-
.option('-u, --update', 'Check the version to determine whether to update to the latest one.')
38-
.parse(process.argv)
24+
.version(version)
25+
.description(`${description}\n${artFontLogo}\n${aim}`)
26+
.addHelpText('after', lcExamples+love)
27+
.arguments("[identity]")
28+
.option('-t, --today', 'Get a question today.')
29+
.option('-i, --identity <identity>', 'Specify a question by identity.')
30+
.option('-r, --random', 'Get a question randomly.')
31+
.option('-e, --easy', 'Use easy mode.')
32+
.option('-d, --directory <directory>', 'Set the question directory.')
33+
.option('-l, --language [language]', 'Set/Get the code language of question.')
34+
.option('-u, --update','Check the version to determine whether to update to the latest one.')
35+
.parse(process.argv)
3936

4037
const cmdArgs = program.args
4138
const cmdOpts = program.opts()
@@ -51,14 +48,13 @@ const cmdOpts = program.opts()
5148
* -无参获取语言
5249
*/
5350
if (cmdOpts.language) {
54-
if (cmdOpts.language !== true) {
55-
await easyLanguageView(cmdOpts.language)
56-
}
57-
else {
58-
const lang = await getQuestionLanguage()
59-
console.log(`当前CLI语言环境为:${lang}`)
60-
}
61-
process.exit(0)
51+
if(cmdOpts.language!==true){
52+
await easyLanguageView(cmdOpts.language);
53+
}else{
54+
const lang = await getQuestionLanguage();
55+
console.log("当前CLI语言环境为:"+lang);
56+
}
57+
process.exit(0);
6258
}
6359
// 根据dir 参数来设置基本目录
6460
const baseDir = cmdOpts.directory ? path.join(process.cwd(), cmdOpts.directory) : process.cwd()
@@ -72,46 +68,24 @@ if (cmdOpts.update) {
7268
process.exit(0)
7369
}
7470
// 创建
75-
function create(mode, question) {
76-
console.log(`MODE: ${mode}`)
77-
return new Promise((resolve) => {
78-
setQuestion(mode, question)
79-
const questionDir = path.join(baseDir, getQuestionFileName(question))
80-
createQuestion(question, questionDir).then(async (path) => {
81-
if (!path)
82-
path = await createQuestionCopy(question, questionDir)
83-
console.log(`题目[${getQuestionChineseName(question)}]获取成功!\n题目文件地址为:${path}`)
84-
resolve(true)
85-
})
86-
})
87-
}
71+
8872
// 模式对应的action
89-
const callModeAction = {
90-
today: () => {
91-
getQuestionToday().then((question) => {
92-
create('today', question).then(() => {
93-
process.exit(0)
94-
})
95-
})
96-
},
97-
random: () => {
98-
getQuestionRandom().then((question) => {
99-
create('random', question).then(() => {
100-
process.exit(0)
101-
})
102-
})
103-
},
104-
identity: (id) => {
105-
getQuestionById(id).then((question) => {
106-
if (!question?.id) {
107-
console.log(`指定编号: [ ${id} ] 题目不存在.`)
108-
process.exit(0)
109-
}
110-
create('identity', question).then(() => {
111-
process.exit(0)
112-
})
113-
})
114-
},
73+
export const callModeAction = {
74+
'today': () => {
75+
getQuestionToday().then(question=>{
76+
create("today",question, baseDir).then(()=>{
77+
process.exit(0)
78+
});
79+
})
80+
},
81+
'random': () => {
82+
getQuestionRandom().then(question=>{
83+
create("random",question, baseDir).then(()=>{
84+
process.exit(0)
85+
});
86+
})
87+
},
88+
'identity':(id)=> createQuestionById(id, baseDir),
11589
}
11690
// 获取模式和参数
11791
const mode = referMode(cmdArgs, cmdOpts)
+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
2+
import {createQuestion} from "#common/utils/question-handler/createQuestion.js";
3+
import {getQuestionFileName} from "#common/utils/question-handler/getQuestionFileName.js";
4+
import {createQuestionCopy} from "#common/utils/question-handler/createQuestionCopy.js";
5+
import {setQuestion} from "#common/utils/store/controller/question.js";
6+
import {getQuestionChineseName} from "#common/utils/question-handler/getQuestionChineseName.js";
7+
import {getQuestionById} from "#common/utils/question-getter/getQuestionById.js";
8+
import { getQuestionIdBySlug } from '#common/utils/question-handler/getQuestionIdBySlug.js';
9+
import path from "path";
10+
11+
export const create = (mode,question, baseDir)=>{
12+
console.log(`MODE: ${mode}`);
13+
return new Promise(resolve=>{
14+
setQuestion(mode,question);
15+
const questionDir = path.join(baseDir,getQuestionFileName(question))
16+
createQuestion(question,questionDir).then(async (path)=>{
17+
if(!path)path = await createQuestionCopy(question,questionDir);
18+
console.log(`题目[${getQuestionChineseName(question)}]获取成功!\n题目文件地址为:${path}`)
19+
resolve(true)
20+
})
21+
})
22+
}
23+
24+
export const createQuestionByTitleSlug = async(titleSlug, baseDir = process.cwd()) => {
25+
const {question} = await getQuestionIdBySlug(titleSlug);
26+
27+
await createQuestionById(question.questionId, baseDir);
28+
}
29+
export const createQuestionById = async(id, baseDir) => {
30+
const question = await getQuestionById(id);
31+
if(!question?.id) {
32+
console.log(`指定编号: [ ${id} ] 题目不存在.`)
33+
process.exit(0)
34+
}
35+
await create("identity",question, baseDir);
36+
// process.exit(0)
37+
38+
39+
}

common/utils/question-getter/getQuestionById.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { getQuestionDetail } from '../question-handler/getQuestionDetail.js'
22
import { getQuestionSearchJson } from '#resources/headers/questionSearchJson.js'
3-
import { graphql } from '#common/utils/http/graphql.js'
3+
import { graphql } from '#common/utils/http/graphql.js'
44

55
export async function getQuestionById(id) {
66
const base = await graphql(getQuestionSearchJson(id.toString()))

common/utils/question-handler/createQuestion.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ export function createQuestion(question, questionDir) {
1616
if (fs.existsSync(filePath))
1717
resolve(false)
1818
else
19-
createQuestionFile(questionDir, filePath, question).then(path => resolve(path)).catch(e => resolve(false))
19+
createQuestionFile(questionDir, filePath, question).then(path => resolve(path)).catch(e => resolve(false))
2020
})
2121
}
2222
export function createQuestionFile(questionDir, questionFilePath, question) {
@@ -27,7 +27,7 @@ export function createQuestionFile(questionDir, questionFilePath, question) {
2727
fulfillQuestion(questionFilePath, question).then(() => resolve(questionFilePath))
2828
})
2929
})
30-
}
30+
}
3131
catch (e) {
3232
reject(e)
3333
}

common/utils/question-handler/createQuestionCopy.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import { getQuestionFileExtension } from '#common/utils/question-handler/questio
1111
* @returns {Promise<unknown>}
1212
*/
1313
export function createQuestionCopy(question, questionDir) {
14-
if (!question || !question.id)
14+
if (!question || !question.id)
1515
return Promise.reject('question is empty')
1616
const dir = path.dirname(questionDir)
1717
const name = `${question.id}.${question.slug}`

common/utils/question-handler/fulfillQuestion.js

+5-5
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { removeDomTags } from '../functions/removeDomTags.js'
33
import { getTestCase } from './getTestCase.js'
44
import { getQuestionUrl } from './getQuestionUrl.js'
55
import { createMarkdown } from './createMarkdown.js'
6-
import { getQuestionChineseName } from '#common/utils/question-handler/getQuestionChineseName.js'
6+
import { getQuestionChineseName } from '#common/utils/question-handler/getQuestionChineseName.js'
77

88
/**
99
* @typedef {object} Question
@@ -22,7 +22,7 @@ import { getQuestionChineseName } from '#common/utils/question-handler/getQuesti
2222
* @param {Question} question
2323
*
2424
*/
25-
export function generateTemplateContent(data, question) {
25+
export function generateTemplateContent(data, question) {
2626
return data
2727
.replace('@题目', `${getQuestionChineseName(question)} ${question.date ? `[${question.date}]` : ''}`)
2828
.replace('@描述', removeDomTags(question.detail)
@@ -31,7 +31,7 @@ export function generateTemplateContent(data, question) {
3131
.replaceAll('\n', '\n * '))
3232
.replace('// @Function', question.code)
3333
.replace('// @TestCase', getTestCase(question))
34-
.replace('@url', getQuestionUrl(question.slug))
34+
.replace('@url', getQuestionUrl(question.slug))
3535
}
3636
/**
3737
* 填充模板文件
@@ -42,13 +42,13 @@ export function fulfillQuestion(questionPath, question) {
4242
return new Promise((resolve) => {
4343
// 开始填充内容
4444
fs.readFile(questionPath, 'utf8', (err, data) => {
45-
if (err)
45+
if (err)
4646
throw err
4747
// 修改文件内容
4848
const newData = generateTemplateContent(data, question)
4949
createMarkdown(question.detail, questionPath)
5050
fs.writeFile(questionPath, newData, (err) => {
51-
if (err)
51+
if (err)
5252
throw err
5353
resolve()
5454
})
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
2+
3+
import { createQuestionByTitleSlug } from "../create-check/createUtil.js";
4+
import path from "path";
5+
const bodyString = "{\"query\":\"\\n query studyPlanPastSolved($slug: String!) {\\n studyPlanV2Detail(planSlug: $slug) {\\n planSubGroups {\\n slug\\n questions {\\n titleSlug\\n status\\n }\\n }\\n }\\n}\\n \",\"variables\":{\"slug\":\"top-100-liked\"},\"operationName\":\"studyPlanPastSolved\"}"
6+
const headers = {
7+
"content-type": "application/json",
8+
}
9+
10+
11+
const initJson = {
12+
headers,
13+
body: bodyString,
14+
method: "POST"
15+
16+
}
17+
// 抓hot100列表
18+
export const getHot100QuestionList = async() => {
19+
const res = await fetch("https://leetcode.cn/graphql/", initJson).then(res=> res.json())
20+
const { data: {
21+
studyPlanV2Detail
22+
} } = res;
23+
return studyPlanV2Detail
24+
}
25+
26+
// 获取题目列表
27+
export const getTitleSlugList = async () => {
28+
const res = await getHot100QuestionList();
29+
const {planSubGroups} = res;
30+
return planSubGroups.reduce((acc, cur)=> {
31+
acc.push(...cur.questions.map(res=> res.titleSlug))
32+
return acc
33+
}, [])
34+
}
35+
//获取创建promise列表
36+
const getPromiseList = async() => {
37+
const titleSlugList = await getTitleSlugList();
38+
const dir = path.join(process.cwd(), 'hot100')
39+
return titleSlugList.map((titleSlug) => createQuestionByTitleSlug(titleSlug,dir))
40+
41+
}
42+
43+
export async function getHot100QuestionListJSCode () {
44+
const promiseList = await getPromiseList();
45+
return await Promise.all(promiseList)
46+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
const headers = {
2+
"content-type": "application/json",
3+
}
4+
5+
6+
7+
8+
export async function getQuestionIdBySlug(titleSlug) {
9+
10+
const body = {
11+
query: "\n query questionTitle($titleSlug: String!) {\n question(titleSlug: $titleSlug) {\n questionId\n questionFrontendId\n title\n titleSlug\n isPaidOnly\n difficulty\n likes\n dislikes\n categoryTitle\n }\n}\n ",
12+
variables: {
13+
titleSlug,
14+
},
15+
operationName: "questionTitle"
16+
}
17+
const initJson = {
18+
headers,
19+
body: JSON.stringify(body),
20+
method: "POST"
21+
22+
}
23+
const res = await fetch("https://leetcode.cn/graphql/", initJson).then(res=> res.json());
24+
const { data: question} = res;
25+
return question
26+
27+
}
28+
29+
// await getQuestionIdBySlug("group-anagrams")

common/utils/question-handler/getTestCase.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ export function getTestCase(question) {
2727
if (question.lang === DefaultLang) {
2828
const functionName = question.code?.match(/(var|let|const).+=/g)?.[0]?.replace(/((var|let|const)|=)\s?/gm, '').trim()
2929
return `showLogs(\n${functionName},\n{\ndata: [${cases}],\nstructure: ${JSON.stringify(getDataStructure(question.code))},\n},\n{\ndata: [${expires}],\nstructure: ${JSON.stringify(getDataStructure(question.code, 'return'))}\n}\n)`
30-
}
30+
}
3131
else {
3232
// 其他语言无法支持测试 只能提供测试数据
3333
console.log(cases, expires)

common/utils/question-handler/parseStructure.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,12 @@ const paramMap = {
2727
* @param {string[]} structs
2828
* @param {string} type
2929
*/
30-
export function setDataStructure(params, structs, type = 'cases') {
30+
export function setDataStructure(params, structs, type = 'cases') {
3131
return params.map((param, index) => {
3232
const struct = structs[index]
3333
const map = paramMap[type]
3434
return map[struct] ? map[struct](param) : map.default(param)
35-
})
35+
})
3636
}
3737

3838
/**

common/utils/store/schemas/question.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import Realm from 'realm'
1+
import Realm from 'realm'
22

33
export class Question extends Realm.Object {
44
static schema = {

0 commit comments

Comments
 (0)