Skip to content

Commit 692d76d

Browse files
committed
Update new feature
Update new feature for list command to filter problems by company and specific time period.
1 parent 68300c0 commit 692d76d

File tree

3 files changed

+150
-50
lines changed

3 files changed

+150
-50
lines changed

lib/commands/list.js

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,12 @@ const cmd = {
4848
default: '',
4949
describe: 'Filter questions by keyword'
5050
})
51+
.option('p', {
52+
alias: 'time',
53+
type: 'string',
54+
default: "0",
55+
describe: 'Filter questions by selected time period of company questions'
56+
})
5157
.example(chalk.yellow('leetcode list'), 'List all questions')
5258
.example(chalk.yellow('leetcode list -x'), 'Show extra info of questions, e.g. tags')
5359
.example('', '')
@@ -62,7 +68,6 @@ cmd.handler = function(argv) {
6268
session.argv = argv;
6369
core.filterProblems(argv, function(e, problems) {
6470
if (e) return log.fail(e);
65-
6671
const word = argv.keyword.toLowerCase();
6772
if (word) {
6873
if (word.endsWith(word.substr(-1).repeat(6))) {
@@ -78,6 +83,9 @@ cmd.handler = function(argv) {
7883
{id: 'level', title: 'level'},
7984
{id: 'tags', title: 'tags'},
8085
{id: 'companies', title: 'companies'},
86+
{id: 'companies06', title: 'companies 6 months'},
87+
{id: 'companies612', title: 'companies 6-12 months'},
88+
{id: 'companies1224', title: 'companies 12-24 months'},
8189
{id: 'percent', title: 'percent'},
8290
{id: 'category', title: 'category'},
8391
]
@@ -94,14 +102,32 @@ cmd.handler = function(argv) {
94102
if (problem.starred) ++stat.starred;
95103

96104
if(argv.csv){
97-
data.push( {id:problem.fid,
98-
name: '=HYPERLINK("'+problem.link+'","'+problem.name+'")',
99-
level: problem.level,
100-
tags: problem.tags,
101-
companies: problem.companies,
102-
percent: problem.percent.toFixed(2),
103-
category: problem.category
104-
});
105+
if(problem.companyStats!=null){
106+
data.push( {id:problem.fid,
107+
name: '=HYPERLINK("'+problem.link+'","'+problem.name+'")',
108+
level: problem.level,
109+
tags: problem.tags,
110+
companies: problem.companies,
111+
companies06: problem.companyStats["1"].join(','),
112+
companies612: problem.companyStats["2"].join(','),
113+
companies1224: problem.companyStats["3"].join(','),
114+
percent: problem.percent.toFixed(2),
115+
category: problem.category
116+
});
117+
}
118+
else{
119+
data.push( {id:problem.fid,
120+
name: '=HYPERLINK("'+problem.link+'","'+problem.name+'")',
121+
level: problem.level,
122+
tags: problem.tags,
123+
companies: problem.companies,
124+
// companies06: problem.companyStats["1"].join(','),
125+
// companies612: problem.companyStats["1"].join(',')+problem.companyStats["2"].join(','),
126+
// companies1224: problem.companyStats["1"].join(',')+problem.companyStats["2"].join(',')+problem.companyStats["3"].join(','),
127+
percent: problem.percent.toFixed(2),
128+
category: problem.category
129+
});
130+
}
105131
}
106132
log.printf('%s %s %s [%=4s] %-60s %-6s (%s %%)',
107133
(problem.starred ? chalk.yellow(icon.like) : icon.empty),

lib/core.js

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ core.filters = {
3535
};
3636

3737
function hasTag(o, tag) {
38-
return Array.isArray(o) && o.some(x => x.indexOf(tag.toLowerCase()) >= 0);
38+
return Array.isArray(o) && o.some(x => x.toLowerCase().indexOf(tag.toLowerCase()) >= 0);
3939
}
4040

4141
const isLevel = (x, q) => x.level[0].toLowerCase() === q.toLowerCase();
@@ -68,12 +68,21 @@ core.filterProblems = function(opts, cb) {
6868
problems = problems.filter(x => f(x, q));
6969
}
7070

71-
for (let t of (opts.tag || [])) {
72-
problems = problems.filter(function(x) {
73-
return x.category === t ||
74-
hasTag(x.companies, t) ||
75-
hasTag(x.tags, t);
76-
});
71+
if(opts.time!="0"){
72+
for (let t of (opts.tag || [])) {
73+
problems = problems.filter(function(x) {
74+
return hasTag(x.companyStats[opts.time],t);
75+
});
76+
}
77+
}
78+
else{
79+
for (let t of (opts.tag || [])) {
80+
problems = problems.filter(function(x) {
81+
return x.category === t ||
82+
hasTag(x.companies, t) ||
83+
hasTag(x.tags, t);
84+
});
85+
}
7786
}
7887

7988
return cb(null, problems);

lib/plugins/leetcode.js

Lines changed: 99 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -79,43 +79,108 @@ plugin.getProblems = function(cb) {
7979
};
8080

8181
plugin.getCategoryProblems = function(category, cb) {
82-
log.debug('running leetcode.getCategoryProblems: ' + category);
83-
const opts = plugin.makeOpts(config.sys.urls.problems.replace('$category', category));
84-
85-
spin.text = 'Downloading category ' + category;
86-
request(opts, function(e, resp, body) {
87-
e = plugin.checkError(e, resp, 200);
88-
if (e) return cb(e);
82+
const user = session.getUser();
83+
if (!user.paid){
84+
log.debug('running leetcode.getCategoryProblems: ' + category);
85+
const opts = plugin.makeOpts(config.sys.urls.problems.replace('$category', category));
86+
87+
spin.text = 'Downloading category ' + category;
88+
request(opts, function(e, resp, body) {
89+
e = plugin.checkError(e, resp, 200);
90+
if (e) return cb(e);
91+
92+
const json = JSON.parse(body);
93+
94+
// leetcode permits anonymous access to the problem list
95+
// while we require login first to make a better experience.
96+
if (json.user_name.length === 0) {
97+
log.debug('no user info in list response, maybe session expired...');
98+
return cb(session.errors.EXPIRED);
99+
}
100+
101+
const problems = json.stat_status_pairs
102+
.filter(p => !p.stat.question__hide)
103+
.map(function(p) {
104+
return {
105+
state: p.status || 'None',
106+
id: p.stat.question_id,
107+
fid: p.stat.frontend_question_id,
108+
name: p.stat.question__title,
109+
slug: p.stat.question__title_slug,
110+
link: config.sys.urls.problem.replace('$slug', p.stat.question__title_slug),
111+
locked: p.paid_only,
112+
percent: p.stat.total_acs * 100 / p.stat.total_submitted,
113+
level: h.levelToName(p.difficulty.level),
114+
starred: p.is_favor,
115+
category: json.category_slug
116+
};
117+
});
118+
119+
return cb(null, problems);
120+
});
121+
}
122+
else{
123+
log.debug('running leetcode.getCategoryProblems with Paid User: ' + category);
124+
125+
category = category.charAt(0).toUpperCase() + category.slice(1)
126+
127+
const opts = plugin.makeOpts(config.sys.urls.graphql);
128+
opts.headers.Origin = config.sys.urls.base;
129+
opts.headers.Referer = config.sys.urls.base;
130+
131+
opts.json = true;
132+
opts.body = {
133+
"query":"query allQuestions { stat_status_pairs: allQuestions {\r\n ...questionFields\r\n __typename}\r\n\r\n favoritesLists {\r\n publicFavorites {\r\n ...favoriteFields\r\n __typename\r\n }\r\n privateFavorites {\r\n ...favoriteFields\r\n __typename\r\n }\r\n __typename\r\n }\r\n\r\n}\r\n \r\nfragment favoriteFields on FavoriteNode {\r\n idHash\r\n id\r\n name\r\n isPublicFavorite\r\n viewCount\r\n creator\r\n isWatched\r\n questions {\r\n questionId\r\n title\r\n titleSlug\r\n __typename\r\n }\r\n __typename\r\n}\r\n\r\nfragment questionFields on QuestionNode {\r\n status\r\n questionId\r\n categoryTitle\r\n companyTagStats\r\n questionFrontendId\r\n hide\r\n title\r\n titleSlug\r\n translatedTitle\r\n stats\r\n difficulty\r\n isPaidOnly\r\n topicTags {\r\n name\r\n translatedName\r\n slug\r\n __typename\r\n }\r\n frequencyTimePeriod\r\n __typename\r\n}"
134+
}
135+
spin.text = 'Downloading category ' + category;
136+
request(opts, function(e, resp, body) {
137+
log.debug('finish request' );
138+
e = plugin.checkError(e, resp, 200);
139+
if (e) return cb(e);
89140

90-
const json = JSON.parse(body);
141+
const json = body;
142+
var starList =[]
143+
for(var favorList in json.data.favoritesLists.privateFavorites){
144+
for(var question in favorList.questions){
145+
startList.push(parseInt(question.questionId))
146+
}
147+
}
148+
149+
const problems = json.data.stat_status_pairs
150+
.filter(p => !p.hide)
151+
.filter(p => p.categoryTitle==category)
152+
.map(function(p) {
153+
var stats = JSON.parse(p.stats)
154+
var companyStats = JSON.parse(p.companyTagStats)
155+
for (var val in companyStats){
156+
companyStats[val] = companyStats[val].map(function(p){
157+
return p.name
158+
})
159+
}
160+
companyStats["2"] = companyStats["2"].concat(companyStats["1"]);
161+
companyStats["3"] = companyStats["3"].concat(companyStats["2"]);
162+
return {
163+
state: p.status || 'None',
164+
id: p.questionId, //string to int
165+
fid: p.questionFrontendId,
166+
name: p.title,
167+
slug: p.titleSlug,
168+
link: config.sys.urls.problem.replace('$slug', p.titleSlug),
169+
locked: p.isPaidOnly,
170+
percent: stats.totalAcceptedRaw * 100 / stats.totalSubmissionRaw,
171+
level: p.difficulty,
172+
starred: starList.includes(p.questionId),
173+
companyStats:companyStats,
174+
category: p.categoryTitle.toLowerCase()
175+
};
176+
});
177+
178+
log.debug('finish parse with Paid User' );
179+
return cb(null, problems);
180+
});
181+
}
91182

92-
// leetcode permits anonymous access to the problem list
93-
// while we require login first to make a better experience.
94-
if (json.user_name.length === 0) {
95-
log.debug('no user info in list response, maybe session expired...');
96-
return cb(session.errors.EXPIRED);
97-
}
98183

99-
const problems = json.stat_status_pairs
100-
.filter(p => !p.stat.question__hide)
101-
.map(function(p) {
102-
return {
103-
state: p.status || 'None',
104-
id: p.stat.question_id,
105-
fid: p.stat.frontend_question_id,
106-
name: p.stat.question__title,
107-
slug: p.stat.question__title_slug,
108-
link: config.sys.urls.problem.replace('$slug', p.stat.question__title_slug),
109-
locked: p.paid_only,
110-
percent: p.stat.total_acs * 100 / p.stat.total_submitted,
111-
level: h.levelToName(p.difficulty.level),
112-
starred: p.is_favor,
113-
category: json.category_slug
114-
};
115-
});
116-
117-
return cb(null, problems);
118-
});
119184
};
120185

121186
plugin.getProblem = function(problem, cb) {

0 commit comments

Comments
 (0)