Skip to content

Commit 92c14a6

Browse files
feat: formatted problem data
1 parent dd0cc88 commit 92c14a6

File tree

3 files changed

+88
-51
lines changed

3 files changed

+88
-51
lines changed

src/commands/show.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,4 @@ def show(problem: str = typer.Argument(..., help="Problem slug (e.g., 'two-sum')
1919
typer.echo(typer.style(f"❌ Problem '{problem}' not found", fg=typer.colors.RED))
2020
raise typer.Exit(1)
2121

22-
2322
ProblemDetails(data.get('data', {}).get('question')).display()

src/lib/problem_ui.py

Lines changed: 86 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,19 @@
11
from rich.console import Console
2+
from rich.table import Table
23
from rich.panel import Panel
34
from rich.markdown import Markdown
45
from rich.layout import Layout
56
from rich.box import ROUNDED
7+
from rich.style import Style
68
from rich.text import Text
79
from rich.align import Align
810
from bs4 import BeautifulSoup
911
import json
1012
from dataclasses import dataclass
1113
from typing import List, Dict, Optional
1214

15+
import typer
16+
1317
console = Console()
1418

1519
@dataclass
@@ -20,11 +24,16 @@ class FunctionMetadata:
2024

2125
class ProblemDetails:
2226
def __init__(self, problem_data: dict):
27+
self.data = problem_data
2328
self.question_id: int = problem_data['questionId']
2429
self.title: str = problem_data['title']
2530
self.difficulty: str = problem_data['difficulty']
2631
self.content: str = problem_data['content']
27-
self.test_cases: List[str] = problem_data['exampleTestcases'].split('\n')
32+
self.test_cases: List[str] = (
33+
problem_data['exampleTestcaseList']
34+
if isinstance(problem_data['exampleTestcaseList'], list)
35+
else problem_data.get('exampleTestcases', '').split('\n')
36+
)
2837
self.code_snippets: List[Dict] = problem_data['codeSnippets']
2938

3039
# Parse metadata
@@ -120,7 +129,8 @@ def format_test_case(self, input_str: str, expected_str: str, case_num: int) ->
120129
f"[bold green]Out:[/] {expected_str}"
121130
)
122131

123-
def create_header(self):
132+
def _create_header(self):
133+
"""Create the problem header with title and difficulty"""
124134
difficulty_colors = {
125135
'Easy': 'bright_green',
126136
'Medium': 'yellow',
@@ -129,74 +139,101 @@ def create_header(self):
129139
difficulty_color = difficulty_colors.get(self.difficulty, 'white')
130140

131141
header = Text()
132-
header.append("🔹 ", style="blue")
133142
header.append(f"{self.question_id}. {self.title}", style="bold cyan")
134-
header.append(" ", style="dim")
143+
header.append(" ", style="dim")
135144
header.append(self.difficulty, style=difficulty_color)
136145

137146
return Align.center(header)
138147

148+
def _format_description(self, html_content: str) -> str:
149+
"""Format the problem description, removing example test cases"""
150+
soup = BeautifulSoup(html_content, 'html.parser')
151+
typer.echo(soup.prettify())
152+
153+
# Remove all pre tags and example sections
154+
for pre in soup.find_all('pre'):
155+
pre.decompose()
156+
for strong in soup.find_all('strong', class_='example'):
157+
strong.decompose()
158+
for tag in soup.find_all():
159+
if not tag.get_text(strip=True):
160+
tag.decompose()
161+
162+
# Format remaining HTML elements
163+
for code in soup.find_all('code'):
164+
code.replace_with(BeautifulSoup(f'`{code.text}`', 'html.parser'))
165+
166+
# Format strong and em tags
167+
for strong in soup.find_all('strong'):
168+
strong.replace_with(BeautifulSoup(f'**{strong.text}**', 'html.parser'))
169+
170+
for em in soup.find_all('em'):
171+
em.replace_with(BeautifulSoup(f'_{em.text}_', 'html.parser'))
172+
173+
for pre in soup.find_all('pre'):
174+
lines = pre.text.strip().split('\n')
175+
formatted = '\n'.join(f' {line}' for line in lines)
176+
pre.replace_with(BeautifulSoup(f'\n```\n{formatted}\n```\n', 'html.parser'))
177+
178+
return soup.get_text('\n').strip()
179+
180+
def _format_test_cases(self):
181+
"""Format test cases with explanations"""
182+
test_cases = []
183+
examples = self.test_cases
184+
185+
# Extract example explanations from HTML content
186+
soup = BeautifulSoup(self.content, 'html.parser')
187+
explanations = []
188+
for strong in soup.find_all('strong'):
189+
if 'Example' in strong.text:
190+
parent = strong.find_parent(['p', 'div'])
191+
if parent:
192+
explanations.append(parent.get_text())
193+
194+
# Combine test cases with their explanations
195+
for i, (test, explanation) in enumerate(zip(examples, explanations)):
196+
test_cases.append(
197+
f"[bold blue]Example {i + 1}:[/]\n"
198+
f"[cyan]Input:[/] {test}\n"
199+
f"{explanation.replace('Example ' + str(i + 1) + ':', '[yellow]Explanation:[/]')}"
200+
)
201+
202+
return "\n\n".join(test_cases)
203+
139204
def display(self):
205+
"""Display the problem details"""
206+
# Clear screen and show header
140207
console.clear()
141-
142-
console.print(self.create_header())
208+
console.print(self._create_header())
143209
console.print()
144210

211+
# Create main layout
145212
layout = Layout()
146213
layout.split_row(
147-
Layout(name="left_section"),
148-
Layout(name="sidebar", size=self.console_width // 4)
214+
Layout(name="description", ratio=2),
215+
Layout(name="examples", ratio=1)
149216
)
150217

151-
layout["left_section"].split_column(
152-
Layout(name="description", ratio=85),
153-
Layout(name="bottom", ratio=15)
154-
)
155-
156-
# Update description panel
218+
# Description panel
219+
description = self._format_description(self.content)
157220
layout["description"].update(Panel(
158-
Markdown(self.formatted_description, justify="left", style="white"),
221+
Markdown(description),
159222
box=ROUNDED,
160223
title="[bold blue]Description",
161224
border_style="blue",
162-
padding=(1, 2),
163-
expand=True
164-
))
165-
166-
# Update sidebar panel
167-
sidebar_content = (
168-
f"{self.formatted_function_signature}\n\n"
169-
"[bold blue]Available Languages:[/]\n"
170-
f"[green]{self.available_languages}[/]"
171-
)
172-
173-
layout["sidebar"].update(Panel(
174-
sidebar_content,
175-
box=ROUNDED,
176-
border_style="blue",
177-
padding=(1, 2),
178-
expand=True
225+
padding=(1, 2)
179226
))
180227

181-
# Update test cases panel
182-
test_cases_content = []
183-
184-
for i in range(0, len(self.test_cases), 2):
185-
if i + 1 < len(self.test_cases):
186-
case_num = i // 2 + 1
187-
test_case = self.format_test_case(
188-
self.test_cases[i],
189-
self.test_cases[i+1],
190-
case_num
191-
)
192-
test_cases_content.append(test_case)
193-
194-
layout["bottom"].update(Panel(
195-
"\n\n".join(test_cases_content),
228+
# Example test cases panel
229+
test_cases = self._format_test_cases()
230+
layout["examples"].update(Panel(
231+
test_cases,
196232
box=ROUNDED,
197-
title="[bold blue]Sample Test Cases",
233+
title="[bold blue]Examples",
198234
border_style="blue",
199-
padding=(1, 2),
235+
padding=(1, 2)
200236
))
201237

238+
# Display the layout
202239
console.print(layout)

src/server/solution_manager.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ def get_question_data(self, title_slug: str) -> Dict[str, Any]:
2222
titleSlug
2323
content
2424
difficulty
25-
exampleTestcases
25+
exampleTestcaseList
2626
sampleTestCase
2727
metaData
2828
codeSnippets {
@@ -41,6 +41,7 @@ def get_question_data(self, title_slug: str) -> Dict[str, Any]:
4141
"variables": {"titleSlug": title_slug}
4242
}
4343
)
44+
4445
return response.json()
4546

4647
def format_problem_details(self, data: Dict[str, Any]) -> Dict[str, Any]:

0 commit comments

Comments
 (0)