var _ = require('underscore'); var sprintf = require('sprintf-js').sprintf; var h = require('../helper'); var chalk = require('../chalk'); var icon = require('../icon'); var log = require('../log'); var core = require('../core'); var session = require('../session'); var cmd = { command: 'list [keyword]', aliases: ['ls'], desc: 'List questions', builder: function(yargs) { return yargs .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' }) .positional('keyword', { type: 'string', default: '', describe: 'Filter questions by keyword' }) .example(chalk.yellow('leetcode list'), 'List all questions') .example(chalk.yellow('leetcode list array'), 'List questions that has "array" in name') .example(chalk.yellow('leetcode list -q eD'), 'List questions that with easy level and not done') .example(chalk.yellow('leetcode list -t google'), 'List questions from Google company (require plugin)') .example(chalk.yellow('leetcode list -t stack'), 'List questions realted to stack (require plugin)'); } }; function byLevel(x, q) { return x.level[0].toLowerCase() === q.toLowerCase(); } function byStateAC(x, q) { return x.state === 'ac'; } function byLocked(x, q) { return x.locked; } function byStarred(x, q) { return x.starred; } var QUERY_HANDLERS = { e: byLevel, E: _.negate(byLevel), m: byLevel, M: _.negate(byLevel), h: byLevel, H: _.negate(byLevel), l: byLocked, L: _.negate(byLocked), d: byStateAC, D: _.negate(byStateAC), s: byStarred, S: _.negate(byStarred) }; function hasTag(o, tag) { return _.isArray(o) && _.some(o, function(x) { return x.indexOf(tag.toLowerCase()) >= 0; }); } cmd.handler = function(argv) { session.argv = argv; core.getProblems(function(e, problems) { if (e) return log.fail(e); var all = problems.length; if (argv.query) { argv.query.split('').forEach(function(q) { var f = QUERY_HANDLERS[q]; if (!f) return; problems = _.filter(problems, _.partial(f, _, q)); }); } argv.tag.forEach(function(tag) { // TODO: fill company/tags in problems problems = _.filter(problems, function(p) { return p.category === tag || hasTag(p.companies, tag) || hasTag(p.tags, tag); }); }); var word = String(argv.keyword).toLowerCase(); if (word) { if (word.endsWith(word.substr(-1).repeat(6))) { log.warn('Hmmm...you might need a new keyboard?'); } problems = _.filter(problems, function(x) { return x.name.toLowerCase().indexOf(word) >= 0; }); } var stat = {}; var KEYS = ['locked', 'starred', 'ac', 'notac', 'None', 'Easy', 'Medium', 'Hard']; KEYS.forEach(function(x) { stat[x] = 0; }); problems = _.sortBy(problems, function(x) { return -x.id; }); problems.forEach(function(problem) { stat[problem.level] = (stat[problem.level] || 0) + 1; stat[problem.state] = (stat[problem.state] || 0) + 1; if (problem.locked) ++stat.locked; if (problem.starred) ++stat.starred; log.printf('%s %s %s [%3d] %-60s %-6s (%.2f %%)', (problem.starred ? chalk.yellow(icon.like) : icon.none), (problem.locked ? chalk.red(icon.lock) : icon.none), h.prettyState(problem.state), problem.id, problem.name, h.prettyLevel(sprintf('%-6s', problem.level)), problem.percent); }); if (argv.stat) { log.info(); log.printf(' All: %-9d Listed: %-9d', all, problems.length); log.printf(' Locked: %-9d Starred: %-9d', stat.locked, stat.starred); log.printf(' Accept: %-9d Not-AC: %-9d New: %-9d', stat.ac, stat.notac, stat.None); log.printf(' Easy: %-9d Medium: %-9d Hard: %-9d', stat.Easy, stat.Medium, stat.Hard); } }); }; module.exports = cmd;