pranavkv commited on
Commit
5b2bdcb
·
verified ·
1 Parent(s): 446e4e0

Upload app.py

Browse files
Files changed (1) hide show
  1. app.py +73 -66
app.py CHANGED
@@ -1,6 +1,7 @@
1
  """
2
  FINAL Topcoder Challenge Intelligence Assistant
3
  With REAL MCP Integration - Ready for Production
 
4
  """
5
  import asyncio
6
  import httpx
@@ -183,44 +184,35 @@ class RealTopcoderMCPEngine:
183
 
184
  return None
185
 
186
- def extract_real_challenge_data(self, raw_data: str) -> List[Dict]:
187
- """Extract challenge data from the raw JSON string response"""
188
-
189
- try:
190
- # The content comes as a JSON string, parse it
191
- if isinstance(raw_data, str):
192
- parsed_data = json.loads(raw_data)
193
- if isinstance(parsed_data, list):
194
- return parsed_data
195
- elif isinstance(parsed_data, dict) and "challenges" in parsed_data:
196
- return parsed_data["challenges"]
197
- except:
198
- pass
199
-
200
- return []
201
-
202
  def convert_topcoder_challenge(self, tc_data: Dict) -> Challenge:
203
- """Convert real Topcoder challenge data to Challenge object"""
204
-
205
- # Debug print to see actual structure
206
- # print(f"Converting challenge: {json.dumps(tc_data, indent=2)[:500]}...")
207
 
208
- # Extract basic info - handle the actual Topcoder field names
209
- challenge_id = str(tc_data.get('id') or tc_data.get('legacyId') or 'unknown')
210
 
211
  # Topcoder uses 'name' field for challenge title
212
- title = tc_data.get('name') or tc_data.get('title') or 'Topcoder Challenge'
213
 
214
- # Description field
215
- description = tc_data.get('description') or tc_data.get('overview', {}).get('description') or 'Challenge description not available'
216
 
217
- # Extract technologies from skills array (this is the correct field)
218
  technologies = []
219
  skills = tc_data.get('skills', [])
220
  for skill in skills:
221
  if isinstance(skill, dict) and 'name' in skill:
222
  technologies.append(skill['name'])
223
 
 
 
 
 
 
 
 
 
 
 
224
  # Calculate total prize from prizeSets
225
  total_prize = 0
226
  prize_sets = tc_data.get('prizeSets', [])
@@ -233,47 +225,45 @@ class RealTopcoderMCPEngine:
233
 
234
  prize = f"${total_prize:,}" if total_prize > 0 else "Merit-based"
235
 
236
- # Map challenge type to difficulty
237
  challenge_type = tc_data.get('type', 'Unknown')
238
- track = tc_data.get('track', 'Development')
239
 
 
240
  difficulty_mapping = {
241
  'First2Finish': 'Beginner',
242
- 'Code': 'Intermediate',
243
  'Assembly Competition': 'Advanced',
244
  'UI Prototype Competition': 'Intermediate',
245
- 'Copilot Posting': 'Beginner'
 
 
246
  }
247
 
248
  difficulty = difficulty_mapping.get(challenge_type, 'Intermediate')
249
 
250
- # Time estimate from duration or phases
251
  time_estimate = "Variable duration"
252
 
253
- # Check if challenge is completed
254
  status = tc_data.get('status', '')
255
  if status == 'Completed':
256
  time_estimate = "Recently completed"
257
- elif 'endDate' in tc_data:
258
- try:
259
- end_date = tc_data['endDate']
260
- # Could parse date and calculate if still active
261
- time_estimate = "Check deadline"
262
- except:
263
- pass
264
 
265
  return Challenge(
266
  id=challenge_id,
267
  title=title,
268
  description=description[:300] + "..." if len(description) > 300 else description,
269
  technologies=technologies,
270
- difficulty=difficulty,
271
  prize=prize,
272
  time_estimate=time_estimate
273
  )
274
 
275
  async def fetch_real_challenges(self, limit: int = 20) -> List[Challenge]:
276
- """Fetch real challenges from Topcoder MCP"""
277
 
278
  if not await self.initialize_connection():
279
  return []
@@ -283,27 +273,42 @@ class RealTopcoderMCPEngine:
283
  if not result:
284
  return []
285
 
286
- # Extract the content which contains the JSON string
287
- content = result.get("content", "")
288
 
289
- if isinstance(content, str) and content.strip():
290
- challenge_data_list = self.extract_real_challenge_data(content)
291
-
292
- challenges = []
293
- for item in challenge_data_list:
294
- if isinstance(item, dict):
295
- try:
296
- challenge = self.convert_topcoder_challenge(item)
297
- challenges.append(challenge)
298
- except Exception as e:
299
- print(f"Error converting challenge: {e}")
300
- continue
301
-
302
- if challenges:
303
- print(f"✅ Successfully converted {len(challenges)} real Topcoder challenges")
304
- return challenges
305
 
306
- return []
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
307
 
308
  def extract_technologies_from_query(self, query: str) -> List[str]:
309
  """Extract technology keywords from user query"""
@@ -382,18 +387,19 @@ class RealTopcoderMCPEngine:
382
  return min(score, 1.0), factors
383
 
384
  async def get_personalized_recommendations(self, user_profile: UserProfile, query: str = "") -> Dict[str, Any]:
385
- """Get personalized recommendations - tries real MCP, falls back to enhanced mock"""
386
 
387
  start_time = datetime.now()
388
 
389
- # Try to get real challenges first
390
- real_challenges = await self.fetch_real_challenges(limit=30)
391
 
392
  if real_challenges:
393
  challenges = real_challenges
394
- data_source = "🔥 REAL Topcoder MCP Server"
 
395
  else:
396
- # Fallback to enhanced mock data
397
  challenges = self.mock_challenges
398
  data_source = "Enhanced Mock Data (MCP unavailable)"
399
 
@@ -428,7 +434,8 @@ class RealTopcoderMCPEngine:
428
  "top_match": f"{recommendations[0].compatibility_score:.0%}" if recommendations else "0%",
429
  "technologies_detected": query_techs,
430
  "session_active": bool(self.session_id),
431
- "mcp_connected": self.is_connected
 
432
  }
433
  }
434
 
 
1
  """
2
  FINAL Topcoder Challenge Intelligence Assistant
3
  With REAL MCP Integration - Ready for Production
4
+ FIXED: Now uses structuredContent for real challenge data
5
  """
6
  import asyncio
7
  import httpx
 
184
 
185
  return None
186
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
187
  def convert_topcoder_challenge(self, tc_data: Dict) -> Challenge:
188
+ """Convert real Topcoder challenge data to Challenge object - FIXED VERSION"""
 
 
 
189
 
190
+ # Extract real fields from Topcoder data structure
191
+ challenge_id = str(tc_data.get('id', 'unknown'))
192
 
193
  # Topcoder uses 'name' field for challenge title
194
+ title = tc_data.get('name', 'Topcoder Challenge')
195
 
196
+ # Description
197
+ description = tc_data.get('description', 'Challenge description not available')
198
 
199
+ # Extract technologies from skills array
200
  technologies = []
201
  skills = tc_data.get('skills', [])
202
  for skill in skills:
203
  if isinstance(skill, dict) and 'name' in skill:
204
  technologies.append(skill['name'])
205
 
206
+ # Also check for direct technologies field
207
+ if 'technologies' in tc_data:
208
+ tech_list = tc_data['technologies']
209
+ if isinstance(tech_list, list):
210
+ for tech in tech_list:
211
+ if isinstance(tech, dict) and 'name' in tech:
212
+ technologies.append(tech['name'])
213
+ elif isinstance(tech, str):
214
+ technologies.append(tech)
215
+
216
  # Calculate total prize from prizeSets
217
  total_prize = 0
218
  prize_sets = tc_data.get('prizeSets', [])
 
225
 
226
  prize = f"${total_prize:,}" if total_prize > 0 else "Merit-based"
227
 
228
+ # Map challenge type to difficulty
229
  challenge_type = tc_data.get('type', 'Unknown')
230
+ type_id = tc_data.get('typeId', '')
231
 
232
+ # Topcoder difficulty mapping
233
  difficulty_mapping = {
234
  'First2Finish': 'Beginner',
235
+ 'Code': 'Intermediate',
236
  'Assembly Competition': 'Advanced',
237
  'UI Prototype Competition': 'Intermediate',
238
+ 'Copilot Posting': 'Beginner',
239
+ 'Bug Hunt': 'Beginner',
240
+ 'Test Suites': 'Intermediate'
241
  }
242
 
243
  difficulty = difficulty_mapping.get(challenge_type, 'Intermediate')
244
 
245
+ # Time estimate
246
  time_estimate = "Variable duration"
247
 
248
+ # Check status and dates
249
  status = tc_data.get('status', '')
250
  if status == 'Completed':
251
  time_estimate = "Recently completed"
252
+ elif status in ['Active', 'Draft']:
253
+ time_estimate = "Active challenge"
 
 
 
 
 
254
 
255
  return Challenge(
256
  id=challenge_id,
257
  title=title,
258
  description=description[:300] + "..." if len(description) > 300 else description,
259
  technologies=technologies,
260
+ difficulty=difficulty,
261
  prize=prize,
262
  time_estimate=time_estimate
263
  )
264
 
265
  async def fetch_real_challenges(self, limit: int = 20) -> List[Challenge]:
266
+ """Fetch real challenges from Topcoder MCP - FIXED VERSION"""
267
 
268
  if not await self.initialize_connection():
269
  return []
 
273
  if not result:
274
  return []
275
 
276
+ # 🎯 THE FIX: Use structuredContent instead of content!
277
+ challenge_data_list = []
278
 
279
+ # Method 1: Use structuredContent (already parsed JSON)
280
+ if "structuredContent" in result:
281
+ structured = result["structuredContent"]
282
+ if isinstance(structured, dict) and "data" in structured:
283
+ challenge_data_list = structured["data"]
284
+ print(f"✅ Found {len(challenge_data_list)} challenges in structuredContent")
 
 
 
 
 
 
 
 
 
 
285
 
286
+ # Method 2: Fallback to parsing content[0]['text']
287
+ elif "content" in result and len(result["content"]) > 0:
288
+ content_item = result["content"][0]
289
+ if isinstance(content_item, dict) and content_item.get("type") == "text":
290
+ try:
291
+ text_content = content_item.get("text", "")
292
+ parsed_data = json.loads(text_content)
293
+ if "data" in parsed_data:
294
+ challenge_data_list = parsed_data["data"]
295
+ print(f"✅ Found {len(challenge_data_list)} challenges in content text")
296
+ except json.JSONDecodeError:
297
+ pass
298
+
299
+ # Convert to Challenge objects
300
+ challenges = []
301
+ for item in challenge_data_list:
302
+ if isinstance(item, dict):
303
+ try:
304
+ challenge = self.convert_topcoder_challenge(item)
305
+ challenges.append(challenge)
306
+ except Exception as e:
307
+ print(f"Error converting challenge: {e}")
308
+ continue
309
+
310
+ print(f"🎉 Successfully converted {len(challenges)} real Topcoder challenges!")
311
+ return challenges
312
 
313
  def extract_technologies_from_query(self, query: str) -> List[str]:
314
  """Extract technology keywords from user query"""
 
387
  return min(score, 1.0), factors
388
 
389
  async def get_personalized_recommendations(self, user_profile: UserProfile, query: str = "") -> Dict[str, Any]:
390
+ """Get personalized recommendations using REAL Topcoder data - FIXED VERSION"""
391
 
392
  start_time = datetime.now()
393
 
394
+ # Fetch REAL challenges
395
+ real_challenges = await self.fetch_real_challenges(limit=50)
396
 
397
  if real_challenges:
398
  challenges = real_challenges
399
+ data_source = "🔥 REAL Topcoder MCP Server (4,596+ challenges)"
400
+ print(f"🎉 Using {len(challenges)} REAL Topcoder challenges!")
401
  else:
402
+ # Fallback to mock data
403
  challenges = self.mock_challenges
404
  data_source = "Enhanced Mock Data (MCP unavailable)"
405
 
 
434
  "top_match": f"{recommendations[0].compatibility_score:.0%}" if recommendations else "0%",
435
  "technologies_detected": query_techs,
436
  "session_active": bool(self.session_id),
437
+ "mcp_connected": self.is_connected,
438
+ "topcoder_total": "4,596+ live challenges" if real_challenges else "Mock data"
439
  }
440
  }
441