Closed 152334H closed 9 months ago
hey @152334H ! really appreciate ur awesome work! will you continue on this or need some help?
i suggest closing it, i really have no time to touch this anymore
also i think it broke at least 3 months ago
i suggest closing it, i really have no time to touch this anymore
haha understood! thank you for your contribution! It's been a long time for me as well having no time contributing to the open source projects, I'll take over this and continue your work! will ask for your reviews once I complete it, is that okay for you?
i mean sure I can look at it, but there's not much i'll remember from last year
TL;DR
You can play leetcode contests on this fork. I played last weekend's contests with this; see the User Experience example.
I want feedback for anything and everything -- code smells, CLI design, even "this sucks and I'm rejecting it".
New feature: Playing with contests in leetcode-cli
This is a short overview of the work I've done to get leetcode contests working in this app. First, I cover the client-server relationship for leetcode contests. Then, I briefly explain the architectural decisions I made in implementation. Finally, I demonstrate what usage of the new
leetcode contest
command looks like, and go over possible changes.The git commit history for this PR is dirty; it might be easier to see the files changed here.
Map of the Leetcode contest API
Contests are stored in the leetcode backend as the
ContestNode
type (see next section), which mostly corresponds to the information available atleetcode.com/contest/$slug
. We can retrieve information by queryinghttps://leetcode.com/contest/api/info/$contest_slug
, or{ contest(titleSlug: String!) }
Before a contest begins, users must register for the contest to participate in it. This can be done with a simple empty POST request to
https://leetcode.com/contest/api/$contest_slug/register
Once a contest starts, the client needs to make additional requests to the leetcode API to get information about the contest problems. For normal
leetcode.com
users, the information appears to be dumped directly into HTML inside a<script>
tag. I did not want to implement/import a full blown HTML parser || use a horrible string/regex search hack, so I found an alternative:{ question(titleSlug: String!) }
queries). There are some differences between the data returned for a contest problem and a normal problem, and they will need to be handled later in the CLI's code.After the user finishes implementing the solution for a problem, they need to submit their code to be judged by the leetcode runtime. A dedicated contest API submission route must be used; running code via the normal API routes "works" but doesn't count for gaining contest points.
https://leetcode.com/contest/api/$contest/problems/$slug/interpret_solution/
https://leetcode.com/contest/api/$contest/problems/$slug/submit/
Users might also want to check the contest scoreboard to see their position. I have not worked on querying/implementing this yet.
Interlude: what's what the
fun
command?Leetcode's API is not documented (at all). I discovered all of the information in the section above by a mixture of the Firefox Dev Console && unsolicited queries to
leetcode.com/graphql
. The latter is what thefun
subcommand is for; I made it as a quick debugging tool to enumerate leetcode's graphql API.As an example, you can get the structure of a
ContestQuestionNode
like this:None of this is needed for a normal user of leetcode-cli, of course, so I will probably remove it unless you think it would be a good idea to keep it.
IMPLEMENTATION
So, how does the API translate to code?
We need some way to expose the following operations to the user: 1, get contest info (given a slug, like
"weekly-contest-295"
)Because contest problems are structurally identical to normal leetcode problems, (4) is actually already solved -- the code for the
test
/exec
commands can be used here, with a little modification. (3) is also mostly solved by the existing code, but there are a few issues:conf.sys.urls["problem"]
) to read problem descriptions, so I added a longer graphql query (Leetcode::get_contest_question_detail
) for thatQuestionNode
data from leetcode for each problem will be slightly modified after a contest ends && the contest problems are republished as normal problems. This causes a user's code for a contest problem to "disappear" from leetcode-cli after a contest, because thefrontendQuestionId
for each problem changes && the user's code file in~/.leetcode/code
is no longer tracked properly by leetcode-cli. I have some ideas to handle this, but I haven't done anything about it yet.That leaves (2) and (1). I added the
Contest
andContestQuestionStub
structs tomodels.rs
; they represent theContestNode
andContestQuestionNode
types from the leetcode graphql API. Corresponding methods were added inleetcode,rs
,cache/mod.rs
, andparser.rs
.The data for the contest structs could (and should) easily be cached, but for the time being I have only implemented direct queries for these structs from the leetcode API.
I've also made a substantial number of changes to existing bodies of code, so it's entirely possible I've accidentally broken a feature or two at some point. I've tried to add TODOs to places where I think the code will probably need to change, but there is probably more.
UX
Currently, the end-user experience with leetcode-cli looks like this:
This system works well enough, but it could definitely be a lot more ergonomic. I was hoping to implement an ncurses-like interface for contests, but
leetcode-cli
as a subprocessNonetheless, the current output of the
contest
command is rather ugly, and more work ought to be done here.End