44from rich import box
55from datetime import datetime
66
7- import typer
8-
97console = Console ()
108
119def format_timestamp (timestamp ):
1210 dt = datetime .fromtimestamp (timestamp )
1311 return dt .strftime ("%Y-%m-%d %H:%M" )
1412
1513def create_recent_activity (recent_submissions ):
16- if not recent_submissions :
14+ if not recent_submissions or 'recentAcSubmissionList' not in recent_submissions :
1715 return None
1816
1917 table = Table (
@@ -28,67 +26,20 @@ def create_recent_activity(recent_submissions):
2826 table .add_column ("Problem" , style = "cyan" )
2927 table .add_column ("Status" , justify = "center" , width = 8 )
3028
31- for sub in recent_submissions [:5 ]: # Show last 5 submissions
32- status_icon = "[green]✓" if sub ['statusDisplay' ] == "Accepted" else "[red]✗"
29+ for sub in recent_submissions ['recentAcSubmissionList' ][:5 ]:
3330 table .add_row (
34- format_timestamp (sub ['timestamp' ]),
31+ format_timestamp (int ( sub ['timestamp' ]) ),
3532 sub ['title' ],
36- status_icon
33+ "[green]✓"
3734 )
3835
3936 return table
4037
41- def create_profile_header (data ):
42- username = data .get ('matchedUser' , {}).get ('username' , 'Leetcoder' )
43- user_data = data .get ('matchedUser' , {})
44- solved = user_data .get ('submitStatsGlobal' , {}).get ('acSubmissionNum' , [])
45-
46- table = Table .grid (padding = (0 , 2 ))
47- table .add_column (justify = "left" , width = 130 )
48- table .add_column (justify = "left" , width = 45 )
49-
50- # Calculate stats
51- total_solved = next ((item ['count' ] for item in solved if item ['difficulty' ] == 'All' ), 0 )
52- total_problems = next ((item ['count' ] for item in data ['allQuestionsCount' ] if item ['difficulty' ] == 'All' ), 0 )
53- solve_percentage = (total_solved / total_problems ) * 100 if total_problems > 0 else 0
54-
55- # Left column - compact formatting
56- profile_text = (
57- f"[bold cyan]{ username } [/bold cyan]\n "
58- f"Solved: [cyan]{ total_solved } [/cyan]/[cyan]{ total_problems } [/cyan]\n "
59- f"[dim]({ solve_percentage :.1f} %)[/dim]"
60- )
61-
62- # Right column - clean difficulty stats
63- difficulties = ['Easy' , 'Medium' , 'Hard' ]
64- colors = ['green' , 'yellow' , 'red' ]
65- stats_text = []
66-
67- for diff , color in zip (difficulties , colors ):
68- solved_count = next ((item ['count' ] for item in solved if item ['difficulty' ] == diff ), 0 )
69- total_count = next ((item ['count' ] for item in data ['allQuestionsCount' ] if item ['difficulty' ] == diff ), 0 )
70- percentage = (solved_count / total_count ) * 100 if total_count > 0 else 0
71-
72- dots = "●" * int (percentage / 10 ) + "○" * (10 - int (percentage / 10 ))
73- stats_text .append (
74- f"[{ color } ]{ diff :<6} { solved_count :>3} /{ total_count :<4} { dots } { percentage :>5.1f} %[/{ color } ]"
75- )
76-
77- table .add_row (
78- profile_text ,
79- "\n " .join (stats_text )
80- )
81-
82- return Panel (
83- table ,
84- border_style = "cyan" ,
85- padding = (1 , 2 ),
86- title = "[bold cyan]LeetCode Profile[/bold cyan]"
87- )
88-
8938def display_user_stats (data ):
9039 console .clear ()
91- console .print ("\n " )
40+ width = min (console .width - 4 , 150 ) # Limit max width
41+ first_width = width // 3 - 2
42+ second_width = (width * 2 ) // 3 - 2
9243
9344 if not data .get ('userProfile' ):
9445 console .print (Panel ("Could not fetch user profile" , border_style = "red" ))
@@ -97,59 +48,90 @@ def display_user_stats(data):
9748 user = data ['userProfile' ]['matchedUser' ]
9849 profile = user ['profile' ]
9950
100- # Display basic profile info
101- profile_table = Table .grid (padding = (0 , 2 ))
51+ # Create main profile info
52+ profile_table = Table .grid (padding = (0 , 1 ))
10253 profile_table .add_column (justify = "left" )
103-
10454 profile_info = [
10555 f"[bold cyan]{ user ['username' ]} [/bold cyan]" ,
10656 f"[dim]Ranking:[/dim] { profile ['ranking' ]} " ,
10757 f"[dim]Company:[/dim] { profile ['company' ] or 'Not specified' } " ,
10858 f"[dim]Location:[/dim] { profile ['countryName' ] or 'Not specified' } "
10959 ]
110-
11160 if profile ['skillTags' ]:
11261 skills = ", " .join (profile ['skillTags' ])
11362 profile_info .append (f"[dim]Skills:[/dim] { skills } " )
114-
11563 profile_table .add_row ("\n " .join (profile_info ))
116- console .print (Panel (profile_table , title = "[bold cyan]Profile Info[/bold cyan]" , border_style = "cyan" ))
117- console .print ("\n " )
11864
119- # Display contest info if available
65+ # Create contest stats if available
66+ contest_panel = None
12067 if data .get ('contestInfo' ) and data ['contestInfo' ].get ('userContestRanking' ):
12168 contest = data ['contestInfo' ]['userContestRanking' ]
122- contest_table = Table .grid (padding = (0 , 2 ))
69+ contest_table = Table .grid (padding = (0 , 1 ))
12370 contest_table .add_column (justify = "left" )
12471 contest_table .add_row (
125- f"Rating: [yellow]{ contest ['rating' ]} [/yellow]\n "
126- f"Global Rank: { contest ['globalRanking' ]} / { contest [ 'totalParticipants' ] } \n "
72+ f"[yellow]Rating: { contest ['rating' ]} [/yellow]\n "
73+ f"Global Rank: { contest ['globalRanking' ]} \n "
12774 f"Top: { contest ['topPercentage' ]} %\n "
12875 f"Contests: { contest ['attendedContestsCount' ]} "
12976 )
130- console .print (Panel (contest_table , title = "[bold yellow]Contest Stats[/bold yellow]" , border_style = "yellow" ))
131- console .print ("\n " )
77+ contest_panel = Panel (
78+ contest_table ,
79+ title = "[bold yellow]Contest Stats[/bold yellow]" ,
80+ border_style = "yellow" ,
81+ width = second_width
82+ )
83+
84+ # Create top row grid
85+ top_grid = Table .grid (padding = (0 , 2 ))
86+ top_grid .add_column (width = first_width )
87+ top_grid .add_column (width = second_width )
88+ top_grid .add_row (
89+ Panel (profile_table , title = "[bold cyan]Profile Info[/bold cyan]" , border_style = "cyan" ),
90+ contest_panel or ""
91+ )
92+ console .print ("\n " )
93+ console .print (top_grid )
94+ console .print ("\n " )
13295
133- # Display progress
134- if data .get ('progress' ):
135- progress = data ['progress' ]
136- console .print (create_profile_header (progress ))
137- console .print ("\n " )
96+ # Create bottom row grid
97+ bottom_grid = Table .grid (padding = (0 , 2 ))
98+ bottom_grid .add_column (width = first_width )
99+ bottom_grid .add_column (width = second_width )
138100
139- # Display language stats
101+ # Language stats
102+ lang_panel = None
140103 if data .get ('languageStats' ):
141104 lang_stats = data ['languageStats' ]['matchedUser' ]['languageProblemCount' ]
142- lang_table = Table (title = "Languages" , box = box .ROUNDED , border_style = "cyan" )
105+ lang_table = Table (
106+ title = "[bold cyan]Languages[/bold cyan]" ,
107+ box = box .ROUNDED ,
108+ border_style = "cyan" ,
109+ padding = (0 , 1 ),
110+ width = first_width
111+ )
143112 lang_table .add_column ("Language" , style = "cyan" )
144- lang_table .add_column ("Problems Solved" , justify = "right" )
113+ lang_table .add_column ("Solved" , justify = "right" )
145114
146115 for lang in sorted (lang_stats , key = lambda x : x ['problemsSolved' ], reverse = True )[:5 ]:
147116 lang_table .add_row (
148117 lang ['languageName' ],
149118 str (lang ['problemsSolved' ])
150119 )
151- console .print (lang_table )
152- console .print ("\n " )
120+ lang_panel = lang_table
121+
122+ # Recent submissions
123+ recent_panel = None
124+ if data .get ('recentAcSubmissions' ):
125+ recent_table = create_recent_activity (data ['recentAcSubmissions' ])
126+ if recent_table :
127+ recent_panel = recent_table
128+
129+ bottom_grid .add_row (
130+ lang_panel or "" ,
131+ recent_panel or ""
132+ )
133+ console .print (bottom_grid )
134+ console .print ("\n " )
153135
154136def display_problem_list (data ):
155137 console .clear ()
0 commit comments