@@ -19,27 +19,102 @@ def create_recent_activity(recent_submissions):
1919 box = box .ROUNDED ,
2020 border_style = "cyan" ,
2121 pad_edge = False ,
22- show_edge = True
22+ show_edge = True ,
23+ width = 65
2324 )
24-
2525 table .add_column ("Time" , style = "dim" , width = 16 )
2626 table .add_column ("Problem" , style = "cyan" )
27- table .add_column ("Status" , justify = "center" , width = 8 )
2827
2928 for sub in recent_submissions ['recentAcSubmissionList' ][:5 ]:
3029 table .add_row (
3130 format_timestamp (int (sub ['timestamp' ])),
3231 sub ['title' ],
33- "[green]✓"
3432 )
33+ return table
34+
35+ def create_progress_panel (data ):
36+ if not data .get ('progress' ):
37+ return None
38+
39+ progress = data ['progress' ]
40+ all_count = progress ['allQuestionsCount' ]
41+ submit_stats = progress ['matchedUser' ]['submitStats' ]
42+ table = Table .grid (padding = (0 , 1 ))
43+ table .add_column (justify = "left" )
44+
45+ for diff in ['Easy' , 'Medium' , 'Hard' ]:
46+ total = next ((q ['count' ] for q in all_count if q ['difficulty' ] == diff ), 0 )
47+ solved = next ((s ['count' ] for s in submit_stats ['acSubmissionNum' ] if s ['difficulty' ] == diff ), 0 )
48+ table .add_row (f"[dim]{ diff } :[/dim] { solved } /{ total } " )
49+
50+ return Panel (table , title = "[bold green]Progress[/bold green]" , border_style = "green" )
51+
52+ def create_social_links (user , websites = None ):
53+ links = []
54+ if user ['githubUrl' ]:
55+ links .append (f"[blue]GitHub[/blue]: { user ['githubUrl' ]} " )
56+ if user ['linkedinUrl' ]:
57+ links .append (f"[blue]LinkedIn[/blue]: { user ['linkedinUrl' ]} " )
58+ if user ['twitterUrl' ]:
59+ links .append (f"[blue]Twitter[/blue]: { user ['twitterUrl' ]} " )
60+
61+ if websites :
62+ for site in websites :
63+ url = f"https://{ site } " if not site .startswith (('http://' , 'https://' )) else site
64+ links .append (f"[blue]Website[/blue]: { url } " )
65+
66+ return "\n " .join (links ) if links else "No social links"
67+
68+ def create_language_stats (data ):
69+ if not data or 'matchedUser' not in data :
70+ return None
71+
72+ lang_stats = data ['matchedUser' ]['languageProblemCount' ]
73+ table = Table .grid (padding = (0 , 1 ))
74+ table .add_column (justify = "left" )
75+ rows = []
76+ sorted_stats = sorted (lang_stats , key = lambda x : x ['problemsSolved' ], reverse = True )
77+
78+ for lang in sorted_stats [:5 ]:
79+ rows .append (f"[dim]{ lang ['languageName' ]} :[/dim] { lang ['problemsSolved' ]} " )
80+
81+ table .add_row ("\n " .join (rows ))
82+ return Panel (table , title = "[bold blue]Languages[/bold blue]" , border_style = "blue" , width = 35 , padding = (0 , 1 ))
83+
84+ def create_contest_stats (contest_info ):
85+ stats = []
86+ rating = contest_info .get ('userContestRanking' , {}).get ('rating' , 0 )
87+ attended = contest_info .get ('userContestRanking' , {}).get ('attendedContestsCount' , 0 )
88+ stats .append (f"[dim]Rating:[/dim] { rating :.1f} " )
89+ stats .append (f"[dim]Contests:[/dim] { attended } " )
90+ return "\n " .join (stats )
91+
92+ def create_skill_stats (data ):
93+ if not data .get ('skillStats' ):
94+ return None
95+
96+ skills = data ['skillStats' ]['matchedUser' ]['tagProblemCounts' ]
97+ table = Table (
98+ title = "[bold magenta]Skills[/bold magenta]" ,
99+ box = box .ROUNDED ,
100+ border_style = "magenta" ,
101+ width = 65 ,
102+ pad_edge = False
103+ )
104+ table .add_column ("Level" , style = "magenta" )
105+ table .add_column ("Tag" , style = "cyan" )
106+ table .add_column ("Solved" , justify = "right" )
107+
108+ for level in ['advanced' , 'intermediate' , 'fundamental' ]:
109+ for skill in skills [level ][:2 ]:
110+ table .add_row (level .capitalize (), skill ['tagName' ], str (skill ['problemsSolved' ]))
35111
36112 return table
37113
38114def display_user_stats (data ):
39115 console .clear ()
40- width = min (console .width - 4 , 150 ) # Limit max width
41- first_width = width // 3 - 2
42- second_width = (width * 2 ) // 3 - 2
116+ width = min (console .width - 4 , 180 )
117+ profile_width , stats_width , progress_width = 65 , 35 , 30
43118
44119 if not data .get ('userProfile' ):
45120 console .print (Panel ("Could not fetch user profile" , border_style = "red" ))
@@ -48,88 +123,77 @@ def display_user_stats(data):
48123 user = data ['userProfile' ]['matchedUser' ]
49124 profile = user ['profile' ]
50125
51- # Create main profile info
52126 profile_table = Table .grid (padding = (0 , 1 ))
53127 profile_table .add_column (justify = "left" )
54128 profile_info = [
55- f"[bold cyan]{ user ['username' ]} [/bold cyan]" ,
56- f"[dim]Ranking:[/dim] { profile ['ranking' ]} " ,
57- f"[dim]Company:[/dim] { profile ['company' ] or 'Not specified' } " ,
58- f"[dim]Location:[/dim] { profile ['countryName' ] or 'Not specified' } "
129+ f"[bold cyan]{ user .get ('username' , 'N/A' )} [/bold cyan]" ,
130+ f"[dim]Name:[/dim] { profile .get ('realName' ) or 'Not specified' } " ,
131+ f"[dim]Ranking:[/dim] { profile .get ('ranking' , 'N/A' )} " ,
59132 ]
60- if profile ['skillTags' ]:
61- skills = ", " .join (profile ['skillTags' ])
62- profile_info .append (f"[dim]Skills:[/dim] { skills } " )
63- profile_table .add_row ("\n " .join (profile_info ))
64133
65- # Create contest stats if available
66- contest_panel = None
67- if data .get ('contestInfo' ) and data ['contestInfo' ].get ('userContestRanking' ):
68- contest = data ['contestInfo' ]['userContestRanking' ]
69- contest_table = Table .grid (padding = (0 , 1 ))
70- contest_table .add_column (justify = "left" )
71- contest_table .add_row (
72- f"[yellow]Rating: { contest ['rating' ]} [/yellow]\n "
73- f"Global Rank: { contest ['globalRanking' ]} \n "
74- f"Top: { contest ['topPercentage' ]} %\n "
75- f"Contests: { contest ['attendedContestsCount' ]} "
76- )
77- contest_panel = Panel (
78- contest_table ,
79- title = "[bold yellow]Contest Stats[/bold yellow]" ,
80- border_style = "yellow" ,
81- width = second_width
82- )
134+ for label , field in [('Company' , 'company' ), ('Job Title' , 'jobTitle' ),
135+ ('School' , 'school' ), ('Location' , 'countryName' )]:
136+ if field in profile and profile [field ]:
137+ profile_info .append (f"[dim]{ label } :[/dim] { profile [field ]} " )
83138
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 " )
139+ if profile .get ('skillTags' ):
140+ profile_info .append (f"[dim]Skills:[/dim] { ', ' .join (profile ['skillTags' ])} " )
95141
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 )
142+ social_links = create_social_links (user , profile .get ('websites' , []))
143+ if social_links != "No social links" :
144+ profile_info .append ("\n " + social_links )
145+
146+ profile_table .add_row ("\n " .join (profile_info ))
147+ profile_panel = Panel (profile_table , title = "[bold cyan]Profile Info[/bold cyan]" ,
148+ border_style = "cyan" , width = profile_width , padding = (0 , 1 ))
149+
150+ stats_table = Table .grid (padding = (0 , 1 ))
151+ stats_table .add_column (justify = "left" )
152+ stats = [
153+ f"[dim]Solutions:[/dim] { profile .get ('solutionCount' , 0 )} ({ profile .get ('solutionCountDiff' , 0 ):+d} )" ,
154+ f"[dim]Reputation:[/dim] { profile .get ('reputation' , 0 )} ({ profile .get ('reputationDiff' , 0 ):+d} )" ,
155+ f"[dim]Views:[/dim] { profile .get ('postViewCount' , 0 )} ({ profile .get ('postViewCountDiff' , 0 ):+d} )" ,
156+ ]
157+ if 'categoryDiscussCount' in profile :
158+ stats .append (f"[dim]Discussions:[/dim] { profile ['categoryDiscussCount' ]} ({ profile .get ('categoryDiscussCountDiff' , 0 ):+d} )" )
159+ stats_table .add_row ("\n " .join (stats ))
160+
161+ progress = create_progress_panel (data )
162+ if progress :
163+ progress .width = progress_width
100164
101- # Language stats
102- lang_panel = None
165+ middle_column = Table .grid (padding = (0 , 1 ))
103166 if data .get ('languageStats' ):
104- lang_stats = data ['languageStats' ]['matchedUser' ]['languageProblemCount' ]
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- )
112- lang_table .add_column ("Language" , style = "cyan" )
113- lang_table .add_column ("Solved" , justify = "right" )
114-
115- for lang in sorted (lang_stats , key = lambda x : x ['problemsSolved' ], reverse = True )[:5 ]:
116- lang_table .add_row (
117- lang ['languageName' ],
118- str (lang ['problemsSolved' ])
119- )
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
167+ middle_column .add_row (create_language_stats (data ['languageStats' ]))
168+ middle_column .add_row ("" )
169+ if data .get ('contestInfo' ):
170+ contest_panel = Panel (create_contest_stats (data ['contestInfo' ]),
171+ title = "[bold yellow]Contest Stats[/bold yellow]" ,
172+ border_style = "yellow" , width = stats_width , padding = (0 , 1 ))
173+ middle_column .add_row (contest_panel )
174+
175+ right_column = Table .grid ()
176+ if progress :
177+ right_column .add_row (progress )
178+ right_column .add_row ("" )
179+ stats_panel = Panel (stats_table , title = "[bold blue]Activity Stats[/bold blue]" ,
180+ border_style = "blue" , width = progress_width , padding = (0 , 1 ))
181+ right_column .add_row (stats_panel )
182+
183+ top_grid = Table .grid (padding = (0 , 2 ))
184+ top_grid .add_row (profile_panel , middle_column , right_column )
128185
186+ bottom_grid = Table .grid (padding = (0 , 2 ))
187+ bottom_grid .add_column (width = 65 )
188+ bottom_grid .add_column (width = 65 )
129189 bottom_grid .add_row (
130- lang_panel or "" ,
131- recent_panel or ""
190+ create_skill_stats ( data ) if data . get ( 'skillStats' ) else "" ,
191+ create_recent_activity ( data [ 'recentAcSubmissions' ]) if data . get ( 'recentAcSubmissions' ) else ""
132192 )
193+
194+ console .print ("\n " )
195+ console .print (top_grid )
196+ console .print ("\n " )
133197 console .print (bottom_grid )
134198 console .print ("\n " )
135199
0 commit comments