Skip to content

Commit 3446b76

Browse files
fix: bug fixes and submission result handling
1 parent ebeeeb5 commit 3446b76

File tree

6 files changed

+125
-63
lines changed

6 files changed

+125
-63
lines changed

src/commands/test.py

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -40,14 +40,18 @@ def test(
4040

4141
if result["success"]:
4242
status_color = typer.colors.GREEN if result["status"] == "Accepted" else typer.colors.RED
43-
typer.echo(typer.style(f"\n✨ Status: {result['status']}", fg=status_color))
43+
status_prefix = "✨" if result['status'] == "Accepted" else "❌"
44+
typer.echo(typer.style(f"\n{status_prefix} Status: {result['status']}", fg=status_color))
4445
if "runtime" in result:
45-
typer.echo(f"⏱️ Runtime: {result['runtime']}")
46+
typer.echo(f"⏱️ Runtime: {result['runtime']}")
4647
if "memory" in result:
4748
typer.echo(f"💾 Memory: {result['memory']}")
48-
typer.echo("\nTest Case Results:")
49-
typer.echo(f"📥 Input: {result['input']}")
50-
typer.echo(f"📤 Your Output: {result['output']}")
51-
typer.echo(f"✅ Expected: {result['expected']}")
49+
typer.echo("\nTest Case Results:\n")
50+
typer.echo(f"📤 Your Output:\n{result['output']}")
51+
typer.echo(f"✅ Expected:\n{result['expected']}")
5252
else:
53-
typer.echo(typer.style(f"\n{result['error']}", fg=typer.colors.RED))
53+
typer.echo(typer.style(f"\n{result['status']}", fg=typer.colors.BRIGHT_RED))
54+
error_message = f"\n{result['error']}"
55+
if result.get('full_error'):
56+
error_message += f"\n\nFull error:\n{result['full_error']}"
57+
typer.echo(typer.style(error_message, fg=typer.colors.RED))

src/lib/ui.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,8 +83,12 @@ def create_language_stats(data):
8383

8484
def create_contest_stats(contest_info):
8585
stats = []
86-
rating = contest_info.get('userContestRanking', {}).get('rating', 0)
87-
attended = contest_info.get('userContestRanking', {}).get('attendedContestsCount', 0)
86+
ranking = contest_info.get('userContestRanking', {}) if contest_info else {}
87+
if not ranking:
88+
return "No contest stats"
89+
90+
rating = ranking.get('rating', 0)
91+
attended = ranking.get('attendedContestsCount', 0)
8892
stats.append(f"[dim]Rating:[/dim] {rating:.1f}")
8993
stats.append(f"[dim]Contests:[/dim] {attended}")
9094
return "\n".join(stats)
@@ -166,7 +170,7 @@ def display_user_stats(data):
166170
if data.get('languageStats'):
167171
middle_column.add_row(create_language_stats(data['languageStats']))
168172
middle_column.add_row("")
169-
if data.get('contestInfo'):
173+
if "contestInfo" in data and data.get('contestInfo'):
170174
contest_panel = Panel(create_contest_stats(data['contestInfo']),
171175
title="[bold yellow]Contest Stats[/bold yellow]",
172176
border_style="yellow", width=stats_width, padding=(0, 1))

src/server/api.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
from gql import gql, Client
22
from gql.transport.requests import RequestsHTTPTransport
3+
from src.server.session_manager import SessionManager
34
import requests
5+
import typer
46

57
def create_leetcode_client(csrf_token: str, session_id: str):
68
headers = {
@@ -20,7 +22,14 @@ def create_leetcode_client(csrf_token: str, session_id: str):
2022
fetch_schema_from_transport=False
2123
)
2224

23-
def fetch_user_profile(username: str = "yuvrajsinh5252"):
25+
def fetch_user_profile():
26+
session = SessionManager().load_session()
27+
username = session.get("user_name") if session else None
28+
29+
if not username:
30+
typer.echo(typer.style("❌ Please login first using the login command", fg=typer.colors.RED))
31+
raise typer.Exit(1)
32+
2433
client = create_leetcode_client("csrf_token", "session_id")
2534
queries = {
2635
"userProfile": """

src/server/solution_manager.py

Lines changed: 87 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
from typing import Dict, Any
22
import time
3-
import json
4-
import typer
53

64
class 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"}

temp.cpp

Whitespace-only changes.

two-sum.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
from typing import List
2+
3+
class Solution:
4+
def twoSum(self, nums: List[int], target: int) -> List[int]:
5+
n = len(nums)
6+
for i in range(n - 1):
7+
for j in range(i + 1, n):
8+
if nums[i] + nums[j] == target:
9+
return [i, j]
10+
return []

0 commit comments

Comments
 (0)