Skip to content

Commit

Permalink
Merge pull request #290 from ccagml/main
Browse files Browse the repository at this point in the history
获取题解中增加选项 获取题目的提示
  • Loading branch information
ccagml authored Feb 3, 2024
2 parents 547c6a2 + e96e423 commit b1c0643
Show file tree
Hide file tree
Showing 10 changed files with 163 additions and 23 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# version 3.1.15

- 获取题解中增加选项 获取题目的提示

# version 3.1.14

- 修复 中文题解 如果没有选择对应选项,选择取消会报错
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "vscode-leetcode-problem-rating",
"displayName": "LeetCode",
"description": "%main.description%",
"version": "3.1.14",
"version": "3.1.15",
"author": "ccagml",
"publisher": "ccagml",
"license": "MIT",
Expand Down
9 changes: 9 additions & 0 deletions src/childCall/childCallModule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,15 @@ class ExecuteService implements Disposable {
return solution;
}

public async getHints(input: string): Promise<string> {
// solution don't support translation
const cmd: string[] = [await this.getLeetCodeBinaryPath(), "query", input, "-h"];

let solution = await this.callWithMsg("正在获取提示~~~", this.nodeExecutable, cmd);

return solution;
}

public async tryCnMulSolution(_, child_process, resolve, reject) {
child_process.stdout?.on("data", async (data: string | Buffer) => {
data = data.toString();
Expand Down
20 changes: 15 additions & 5 deletions src/controller/TreeViewController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -529,6 +529,12 @@ class TreeViewController implements Disposable {
description: "",
detail: "",
value: "en",
},
{
label: "获取提示",
description: "",
detail: "",
value: "cnhints",
}
);
const choice: IQuickItemEx<string> | undefined = await vscode.window.showQuickPick(picks);
Expand All @@ -537,11 +543,15 @@ class TreeViewController implements Disposable {
}

try {
const needTranslation: boolean = isUseEndpointTranslation();
const solution: string = await BABA.getProxy(BabaStr.ChildCallProxy)
.get_instance()
.getHelp(problemInput, language, needTranslation, choice.value == "cn");
BABA.getProxy(BabaStr.SolutionProxy).show(solution);
if (choice.value == "cn" || choice.value == "en") {
const solution: string = await BABA.getProxy(BabaStr.ChildCallProxy)
.get_instance()
.getHelp(problemInput, language, isUseEndpointTranslation(), choice.value == "cn");
BABA.getProxy(BabaStr.SolutionProxy).show(solution);
} else if (choice.value == "cnhints") {
const hints: string = await BABA.getProxy(BabaStr.ChildCallProxy).get_instance().getHints(problemInput);
BABA.getProxy(BabaStr.SolutionProxy).show(hints, true);
}
} catch (error) {
BABA.getProxy(BabaStr.LogOutputProxy).get_log().appendLine(error.toString());
await ShowMessage("Failed to fetch the top voted solution. 请查看控制台信息~", OutPutType.error);
Expand Down
16 changes: 16 additions & 0 deletions src/rpc/actionChain/chainNode/cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,22 @@ problems from the next layer. */
sessionUtils.deleteCodingSession();
return user;
};

public getHintsOnline = (problem, cb) => {
const hints = storageUtils.getCache(commUtils.KEYS.hints) || {};
if (hints && hints[problem.id]) {
return cb(null, hints[problem.id]);
}
this.next.getHintsOnline(problem, function (e, hints_result) {
if (e) return cb(e);

const hints = storageUtils.getCache(commUtils.KEYS.hints) || {};
hints[problem.id] = hints_result;
storageUtils.setCache(commUtils.KEYS.hints, hints);

return cb(null, hints_result);
});
};
}

export const pluginObj: CachePlugin = new CachePlugin();
30 changes: 30 additions & 0 deletions src/rpc/actionChain/chainNode/leetcode.cn.ts
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,36 @@ class LeetCodeCn extends ChainNodeBase {
this.next.getHelpOnline(problem, cn_flag, lang);
}
};

getHintsOnline = (problem, cb) => {
getSolutionHints(problem.slug, cb);
};
}

function getSolutionHints(question_slug: string, cb) {
const opts = makeOpts(configUtils.sys.urls.graphql);
opts.headers.Origin = configUtils.sys.urls.base;
// let URL_DISCUSSES = "https://leetcode.com/graphql";
let URL_DISCUSS = "https://leetcode.cn/problems/$slug/description/";
opts.headers.Referer = URL_DISCUSS.replace("$slug", question_slug);

opts.json = true;
opts.body = {
operationName: "questionHints",
variables: { titleSlug: question_slug },
query: [
"query questionHints($titleSlug: String!) {",
" question(titleSlug: $titleSlug) {",
" hints",
" }",
"}",
].join("\n"),
};

request.post(opts, function (e, _, body) {
let hints = body?.data?.question?.hints || [];
cb(e, hints);
});
}

function getSolutionBySlug(question_slug: string, articles_slug: string, lang: string) {
Expand Down
3 changes: 3 additions & 0 deletions src/rpc/actionChain/chainNodeBase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,4 +118,7 @@ export class ChainNodeBase {
public getHelpOnline(problem, cn_flag, lang): void {
this.next.getHelpOnline(problem, cn_flag, lang);
}
public getHintsOnline(problem, cb: Function): void {
this.next.getHintsOnline(problem, cb);
}
}
17 changes: 17 additions & 0 deletions src/rpc/factory/api/queryApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,12 @@ class QueryApi extends ApiBase {
default: configUtils.code.lang,
describe: "getHelp Programming language of the source code",
})
.option("h", {
alias: "hints",
type: "boolean",
default: false,
describe: "get Hints Programming language of the source code",
})
.option("z", {
alias: "test",
type: "string",
Expand Down Expand Up @@ -138,6 +144,17 @@ class QueryApi extends ApiBase {
chainMgr.getChainHead().getHelpOnline(problem, argv.f, argv.g);
});
}
} else if (argv.h) {
if (argv.keyword.length > 0) {
// show specific one
chainMgr.getChainHead().getProblem(argv.keyword, !argv.dontTranslate, function (e, problem) {
if (e) return reply.info(e);
chainMgr.getChainHead().getHintsOnline(problem, function (e, result) {
if (e) return;
reply.info(JSON.stringify({ code: 100, hints: result }));
});
});
}
} else if (argv.z) {
chainMgr.getChainHead().getQueryZ(argv.z, function (e, result) {
if (e) return;
Expand Down
1 change: 1 addition & 0 deletions src/rpc/utils/commUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ class CommUtils {
problems: "problems",
translation: "translationConfig",
ranting_path: "../../rating",
hints_path: "../../hints",
problem: (p) => p.fid + "." + p.slug + "." + p.category,
};
}
Expand Down
84 changes: 67 additions & 17 deletions src/solution/SolutionModule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,30 +19,82 @@ class SolutionService extends BaseWebViewService {
protected readonly viewType: string = "leetcode.solution";
private problemName: string;
private solution: Solution;
private is_hints: boolean;
private hints: Array<string>;

public show(solutionString: string): void {
this.solution = this.parseSolution(solutionString);
if (this.solution.init_data) {
public show(solutionString: string, is_hints: boolean = false): void {
this.is_hints = is_hints;
if (is_hints) {
this.hints = this.parseHints(solutionString);
this.showWebviewInternal();
} else {
this.solution = this.parseSolution(solutionString);
if (this.solution.init_data) {
this.showWebviewInternal();
}
}
}

protected getWebviewOption(): IWebViewOption {
if (BABA.getProxy(BabaStr.PreviewProxy).isSideMode()) {
return {
title: "Solution",
title: this.is_hints ? "Hints" : "Solution",
viewColumn: ViewColumn.Two,
preserveFocus: true,
};
} else {
return {
title: `Solution: ${this.problemName}`,
title: this.is_hints ? "Hints" : `Solution: ${this.problemName}`,
viewColumn: ViewColumn.One,
};
}
}

protected getWebviewContent(): string {
if (this.is_hints) {
return this.getHintsContent();
} else {
return this.getSolutionContent();
}
}

private getHintsContent(): string {
const styles: string = markdownService.getStyles();
let h = this.hints;
let body: Array<any> = [];
if (h.length == 0) {
body.push("本题无提示");
} else {
for (let index = 0; index < h.length; index++) {
const element = h[index];
let hint_body = ["<details><summary>", `提示:${index}`, "</summary>", `${element}`, "</details>"].join("\n");
body.push(hint_body);
}
}
return `
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Security-Policy" content="default-src self; img-src vscode-resource:; script-src vscode-resource: 'self' 'unsafe-inline'; style-src vscode-resource: 'self' 'unsafe-inline'; "/>
${styles}
<link rel="stylesheet" type="text/css" href= "vscode-resource:${path.join(
__dirname,
"..",
"..",
"..",
"resources",
"katexcss",
"kates.min.css"
)}">
</head>
<body class="vscode-body 'scrollBeyondLastLine' 'wordWrap' 'showEditorSelection'" style="tab-size:4">
${body.join("\n")}
</body>
</html>
`;
}

private getSolutionContent(): string {
const styles: string = markdownService.getStyles();
const { title, url, lang, author, votes } = this.solution;
const head: string = markdownService.render(`# [${title}](${url})`);
Expand Down Expand Up @@ -99,16 +151,6 @@ class SolutionService extends BaseWebViewService {
}

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;
let obj = JSON.parse(raw);
let solution: Solution = new Solution();
if (obj.code == 100 && obj.solution) {
Expand All @@ -125,6 +167,14 @@ class SolutionService extends BaseWebViewService {
}
return solution;
}
private parseHints(raw: string): Array<string> {
let obj = JSON.parse(raw);

if (obj.code == 100) {
return obj.hints;
}
return [];
}
}

// tslint:disable-next-line:max-classes-per-file
Expand All @@ -147,8 +197,8 @@ export class SolutionProxy extends BABAProxy {
super(SolutionProxy.NAME);
}

public show(solutionString: string): void {
solutionService.show(solutionString);
public show(solutionString: string, hints: boolean): void {
solutionService.show(solutionString, hints);
}
}

Expand Down

0 comments on commit b1c0643

Please sign in to comment.