11from typing import Dict , Any
22import time
3- import json
4- import typer
53
64class SolutionManager :
75 def __init__ (self , session ):
@@ -81,6 +79,17 @@ def get_question_data(self, question_identifier: str) -> Dict[str, Any]:
8179 def submit_solution (self , title_slug : str , code : str , lang : str = "python3" ) -> Dict [str , Any ]:
8280 """Submit a solution to LeetCode"""
8381 try :
82+ if title_slug .isdigit ():
83+ response = self .session .get (f"{ self .BASE_URL } /api/problems/all/" )
84+ if response .status_code == 200 :
85+ problems = response .json ().get ('stat_status_pairs' , [])
86+ for problem in problems :
87+ if str (problem ['stat' ]['frontend_question_id' ]) == title_slug :
88+ title_slug = problem ['stat' ]['question__title_slug' ]
89+ break
90+ else :
91+ return {"success" : False , "error" : f"Question number { title_slug } not found" }
92+
8493 self ._clean_session_cookies ()
8594
8695 # Get question ID
@@ -93,7 +102,6 @@ def submit_solution(self, title_slug: str, code: str, lang: str = "python3") ->
93102 submit_url = f"{ self .BASE_URL } /problems/{ title_slug } /submit/"
94103
95104 csrf_token = self ._get_csrf_token ()
96- typer .echo (f"Using CSRF token: { csrf_token } " )
97105
98106 headers = {
99107 'referer' : f"{ self .BASE_URL } /problems/{ title_slug } /" ,
@@ -109,33 +117,38 @@ def submit_solution(self, title_slug: str, code: str, lang: str = "python3") ->
109117 "typed_code" : code
110118 }
111119
112- typer .echo (f"Sending request to { submit_url } " )
113120 response = self .session .post (submit_url , json = data , headers = headers )
114121
115122 if response .status_code != 200 :
116- typer .echo (f"Error response: { response .text } " , err = True )
117123 return {"success" : False , "error" : f"Submission failed with status { response .status_code } " }
118124
119125 try :
120126 result_data = response .json ()
121127 submission_id = result_data .get ('submission_id' )
122128 if submission_id :
123- typer .echo (f"Got submission ID: { submission_id } " )
124129 return self .get_submission_result (submission_id )
125130 else :
126- typer .echo ("No submission ID in response" , err = True )
127131 return {"success" : False , "error" : "No submission ID received" }
128132 except ValueError as e :
129- typer .echo (f"Failed to parse response: { response .text } " , err = True )
130133 return {"success" : False , "error" : f"Failed to parse response: { str (e )} " }
131134
132135 except Exception as e :
133- typer .echo (f"Submission error: { str (e )} " , err = True )
134136 return {"success" : False , "error" : f"Submission error: { str (e )} " }
135137
136138 def test_solution (self , title_slug : str , code : str , lang : str = "python3" , full : bool = False ) -> Dict [str , Any ]:
137139 """Test a solution with LeetCode test cases"""
138140 try :
141+ if title_slug .isdigit ():
142+ response = self .session .get (f"{ self .BASE_URL } /api/problems/all/" )
143+ if response .status_code == 200 :
144+ problems = response .json ().get ('stat_status_pairs' , [])
145+ for problem in problems :
146+ if str (problem ['stat' ]['frontend_question_id' ]) == title_slug :
147+ title_slug = problem ['stat' ]['question__title_slug' ]
148+ break
149+ else :
150+ return {"success" : False , "error" : f"Question number { title_slug } not found" }
151+
139152 self ._clean_session_cookies ()
140153
141154 # Get question data first
@@ -153,7 +166,6 @@ def test_solution(self, title_slug: str, code: str, lang: str = "python3", full:
153166 url = f"{ self .BASE_URL } /problems/{ title_slug } /{ endpoint } /"
154167
155168 csrf_token = self .session .cookies .get ('csrftoken' , '' )
156- typer .echo (f"Using CSRF token: { csrf_token } " )
157169
158170 headers = {
159171 'referer' : f"{ self .BASE_URL } /problems/{ title_slug } /" ,
@@ -172,28 +184,23 @@ def test_solution(self, title_slug: str, code: str, lang: str = "python3", full:
172184 'judge_type' : 'small'
173185 }
174186
175- typer .echo (f"Sending request to { url } " )
176187 response = self .session .post (url , json = data , headers = headers )
177188
178189 if response .status_code != 200 :
179- typer .echo (f"Error response: { response .text } " , err = True )
180190 return {"success" : False , "error" : f"Request failed with status { response .status_code } " }
181191
182192 try :
183193 result_data = response .json ()
184194 submission_id = result_data .get (sid_key )
185195 if submission_id :
186- typer .echo (f"Got submission ID: { submission_id } " )
187196 return self .get_test_result (submission_id )
197+ return temp
188198 else :
189- typer .echo ("No submission ID in response" , err = True )
190199 return {"success" : False , "error" : "No submission ID received" }
191200 except ValueError as e :
192- typer .echo (f"Failed to parse response: { response .text } " , err = True )
193201 return {"success" : False , "error" : f"Failed to parse response: { str (e )} " }
194202
195203 except Exception as e :
196- typer .echo (f"Test error: { str (e )} " , err = True )
197204 return {"success" : False , "error" : f"Test error: { str (e )} " }
198205
199206 def _format_output (self , output ) -> str :
@@ -204,61 +211,89 @@ def _format_output(self, output) -> str:
204211 return output .strip ('[]"' )
205212 return str (output )
206213
214+ def _process_submission_result (self , result : Dict [str , Any ], is_test : bool = False ) -> Dict [str , Any ]:
215+ """Process submission/test results and return standardized output"""
216+ if not result .get ('run_success' , True ):
217+ if result .get ('compile_error' ):
218+ return {
219+ "success" : False ,
220+ "status" : "Compilation Error" ,
221+ "error" : result .get ('compile_error' , 'Unknown compilation error' ),
222+ "full_error" : result .get ('full_compile_error' , '' )
223+ }
224+ if result .get ('status_code' ) == 14 :
225+ return {
226+ "success" : False ,
227+ "status" : "Time Limit Exceeded" ,
228+ "error" : "Your code took too long to execute" ,
229+ "runtime" : result .get ('status_runtime' , 'N/A' )
230+ }
231+ return {
232+ "success" : False ,
233+ "status" : "Runtime Error" ,
234+ "error" : result .get ('runtime_error' , 'Unknown runtime error' ),
235+ "full_error" : result .get ('full_runtime_error' , '' )
236+ }
237+
238+ response = {
239+ "success" : True ,
240+ "status" : result .get ('status_msg' , 'Accepted' ),
241+ "runtime" : result .get ('status_runtime' , result .get ('runtime' , 'N/A' )),
242+ "memory" : result .get ('status_memory' , result .get ('memory' , 'N/A' )),
243+ "total_testcases" : result .get ('total_testcases' , 0 ),
244+ "passed_testcases" : result .get ('total_correct' , 0 )
245+ }
246+
247+ if is_test :
248+ code_answers = result .get ('code_answer' , [])
249+ expected_answers = result .get ('expected_code_answer' , [])
250+ is_correct = all (a == b for a , b in zip (code_answers , expected_answers ))
251+
252+ response .update ({
253+ "status" : "Accepted" if is_correct else "Wrong Answer" ,
254+ "output" : self ._format_output (code_answers ),
255+ "expected" : self ._format_output (expected_answers ),
256+ "total_correct" : sum (1 for a , b in zip (code_answers , expected_answers ) if a == b )
257+ })
258+
259+ return response
260+
207261 def get_test_result (self , submission_id : str , timeout : int = 30 ) -> Dict [str , Any ]:
208- """Poll for results with timeout"""
262+ """Poll for test results with timeout"""
209263 url = f"{ self .BASE_URL } /submissions/detail/{ submission_id } /check/"
210- typer .echo (f"Polling for results at { url } " )
211264
212- for i in range (timeout ):
265+ for _ in range (timeout ):
213266 try :
214267 time .sleep (1 )
215- typer .echo (f"Attempt { i + 1 } /{ timeout } ..." )
216-
217268 response = self .session .get (url )
269+
218270 if response .status_code != 200 :
219271 continue
220272
221273 result = response .json ()
222- typer .echo (f"Got response: { json .dumps (result , indent = 2 )} " )
223-
224274 if result .get ('state' ) == 'SUCCESS' :
225- return {
226- "success" : True ,
227- "status" : result .get ('status_msg' , 'Unknown' ),
228- "input" : result .get ('input' , 'N/A' ),
229- "output" : self ._format_output (result .get ('code_answer' , [])),
230- "expected" : self ._format_output (result .get ('expected_code_answer' , [])),
231- "runtime" : result .get ('status_runtime' , 'N/A' ),
232- "memory" : result .get ('status_memory' , 'N/A' ),
233- "total_correct" : result .get ('total_correct' , 0 ),
234- "total_testcases" : result .get ('total_testcases' , 0 )
235- }
275+ return self ._process_submission_result (result , is_test = True )
236276 except Exception as e :
237- typer .echo (f"Error checking result: { str (e )} " , err = True )
238277 continue
239278
240279 return {"success" : False , "error" : "Timeout waiting for results" }
241280
242- def get_submission_result (self , submission_id : str ) -> Dict [str , Any ]:
281+ def get_submission_result (self , submission_id : str , timeout : int = 20 ) -> Dict [str , Any ]:
243282 """Poll for submission results"""
244- check_url = f"{ self .BASE_URL } /submissions/detail/{ submission_id } /check/"
283+ url = f"{ self .BASE_URL } /submissions/detail/{ submission_id } /check/"
245284
246- for _ in range (20 ): #
247- response = self .session .get (check_url )
248- if response .status_code != 200 :
249- return {"success" : False , "error" : f"Failed to get results: { response .status_code } " }
285+ for _ in range (timeout ):
286+ try :
287+ response = self .session .get (url )
288+ if response .status_code != 200 :
289+ continue
250290
251- result = response .json ()
252- if result .get ('state' ) == 'SUCCESS' :
253- return {
254- "success" : True ,
255- "status" : result .get ('status_msg' , 'Unknown' ),
256- "runtime" : result .get ('runtime' , 'N/A' ),
257- "memory" : result .get ('memory' , 'N/A' ),
258- "total_testcases" : result .get ('total_testcases' , 0 ),
259- "passed_testcases" : result .get ('total_correct' , 0 )
260- }
291+ result = response .json ()
292+ if result .get ('state' ) == 'SUCCESS' :
293+ return self ._process_submission_result (result , is_test = False )
261294
262- time .sleep (1 )
295+ time .sleep (1 )
296+ except Exception as e :
297+ continue
263298
264299 return {"success" : False , "error" : "Timeout waiting for results" }
0 commit comments