Upload app.py
Browse files
app.py
CHANGED
|
@@ -338,133 +338,88 @@ class UltimateTopcoderMCPEngine:
|
|
| 338 |
sort_by: str = None,
|
| 339 |
sort_order: str = None,
|
| 340 |
) -> List[Challenge]:
|
| 341 |
-
"""FIXED:
|
| 342 |
|
| 343 |
-
|
| 344 |
-
print(f"π Attempting to fetch REAL challenges (limit: {limit})")
|
| 345 |
print(f"π― Query: '{query}' | Skills: {user_profile.skills}")
|
| 346 |
-
connection_success = await self.initialize_connection()
|
| 347 |
|
|
|
|
|
|
|
| 348 |
if not connection_success:
|
| 349 |
-
print("β Could not establish MCP connection
|
| 350 |
return []
|
| 351 |
|
| 352 |
-
#
|
| 353 |
-
|
| 354 |
|
| 355 |
-
#
|
| 356 |
-
simple_query = {"perPage": min(limit, 20)}
|
| 357 |
if query.strip():
|
| 358 |
-
|
| 359 |
-
query_strategies.append(("Simple Search", simple_query))
|
| 360 |
|
| 361 |
-
#
|
| 362 |
-
|
| 363 |
-
|
| 364 |
-
)
|
| 365 |
-
if skill_keywords:
|
| 366 |
-
skills_query = {"perPage": min(limit, 20)}
|
| 367 |
-
skills_query["tags"] = skill_keywords[:3] # Limit to 3 skills
|
| 368 |
-
query_strategies.append(("Skills Query", skills_query))
|
| 369 |
-
|
| 370 |
-
# Strategy 3: Your comprehensive query
|
| 371 |
-
comprehensive_query = {"perPage": min(limit, 20)}
|
| 372 |
-
if status:
|
| 373 |
-
comprehensive_query["status"] = status
|
| 374 |
-
if query.strip():
|
| 375 |
-
comprehensive_query["search"] = query.strip()
|
| 376 |
-
if sort_by:
|
| 377 |
-
comprehensive_query["sortBy"] = sort_by
|
| 378 |
-
if sort_order:
|
| 379 |
-
comprehensive_query["sortOrder"] = sort_order
|
| 380 |
-
query_strategies.append(("Comprehensive", comprehensive_query))
|
| 381 |
-
|
| 382 |
-
# Try each strategy until one works
|
| 383 |
-
for strategy_name, mcp_query in query_strategies:
|
| 384 |
-
print(f"\nπ§ͺ Trying {strategy_name} strategy:")
|
| 385 |
-
print(f"π§ Query parameters: {mcp_query}")
|
| 386 |
-
|
| 387 |
-
# Call the MCP tool
|
| 388 |
-
result = await self.call_tool("query-tc-challenges", mcp_query)
|
| 389 |
|
| 390 |
-
|
| 391 |
-
print(f"β {strategy_name} failed - no result")
|
| 392 |
-
continue
|
| 393 |
-
|
| 394 |
-
print(f"π {strategy_name} result type: {type(result)}")
|
| 395 |
-
if isinstance(result, dict):
|
| 396 |
-
print(f"π Result keys: {list(result.keys())}")
|
| 397 |
-
|
| 398 |
-
# Show first few characters of each field for debugging
|
| 399 |
-
for key, value in result.items():
|
| 400 |
-
if isinstance(value, str):
|
| 401 |
-
print(f" {key}: {str(value)[:100]}...")
|
| 402 |
-
elif isinstance(value, dict):
|
| 403 |
-
print(f" {key}: dict with keys {list(value.keys())}")
|
| 404 |
-
elif isinstance(value, list):
|
| 405 |
-
print(f" {key}: list with {len(value)} items")
|
| 406 |
-
else:
|
| 407 |
-
print(f" {key}: {type(value)}")
|
| 408 |
|
| 409 |
-
|
| 410 |
-
|
| 411 |
-
|
| 412 |
-
|
| 413 |
-
|
| 414 |
-
|
| 415 |
-
|
| 416 |
-
|
| 417 |
-
|
| 418 |
-
|
| 419 |
-
|
| 420 |
-
|
| 421 |
-
|
| 422 |
-
|
| 423 |
-
|
| 424 |
-
|
|
|
|
|
|
|
|
|
|
| 425 |
|
| 426 |
-
#
|
| 427 |
-
|
| 428 |
-
|
| 429 |
-
|
| 430 |
-
|
| 431 |
-
|
| 432 |
-
|
| 433 |
-
|
| 434 |
-
|
| 435 |
-
|
| 436 |
-
|
| 437 |
-
|
| 438 |
-
|
| 439 |
-
|
| 440 |
-
|
| 441 |
-
|
| 442 |
-
|
| 443 |
-
|
| 444 |
-
|
| 445 |
-
|
| 446 |
-
|
| 447 |
-
|
| 448 |
-
|
| 449 |
-
|
| 450 |
-
|
| 451 |
-
|
| 452 |
-
|
| 453 |
-
print(f"π First challenge: {challenge.title} | {challenge.prize} | {challenge.technologies}")
|
| 454 |
-
except Exception as e:
|
| 455 |
-
print(f"β Error converting challenge {i}: {e}")
|
| 456 |
-
continue
|
| 457 |
-
|
| 458 |
-
if challenges:
|
| 459 |
-
print(f"π SUCCESS with {strategy_name}! Converted {len(challenges)} REAL challenges")
|
| 460 |
-
return challenges
|
| 461 |
-
else:
|
| 462 |
-
print(f"β {strategy_name} - no challenges converted")
|
| 463 |
else:
|
| 464 |
-
print(f"
|
| 465 |
|
| 466 |
-
print("
|
| 467 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 468 |
|
| 469 |
def calculate_advanced_compatibility_score(self, challenge: Challenge, user_profile: UserProfile, query: str) -> tuple:
|
| 470 |
score = 0.0
|
|
|
|
| 338 |
sort_by: str = None,
|
| 339 |
sort_order: str = None,
|
| 340 |
) -> List[Challenge]:
|
| 341 |
+
"""FIXED: Guaranteed to return real challenges when MCP works"""
|
| 342 |
|
| 343 |
+
print(f"π Fetching REAL challenges (limit: {limit})")
|
|
|
|
| 344 |
print(f"π― Query: '{query}' | Skills: {user_profile.skills}")
|
|
|
|
| 345 |
|
| 346 |
+
# Always try to connect
|
| 347 |
+
connection_success = await self.initialize_connection()
|
| 348 |
if not connection_success:
|
| 349 |
+
print("β Could not establish MCP connection")
|
| 350 |
return []
|
| 351 |
|
| 352 |
+
# Build simple query that we KNOW works from debug
|
| 353 |
+
mcp_query = {"perPage": min(limit, 20)}
|
| 354 |
|
| 355 |
+
# Add search term if provided
|
|
|
|
| 356 |
if query.strip():
|
| 357 |
+
mcp_query["search"] = query.strip()
|
|
|
|
| 358 |
|
| 359 |
+
# Add status filter
|
| 360 |
+
if status and status != "":
|
| 361 |
+
mcp_query["status"] = status
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 362 |
|
| 363 |
+
print(f"π§ MCP Query: {mcp_query}")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 364 |
|
| 365 |
+
# Call the MCP tool (we know this works from debug)
|
| 366 |
+
result = await self.call_tool("query-tc-challenges", mcp_query)
|
| 367 |
+
|
| 368 |
+
if not result:
|
| 369 |
+
print("β No result from MCP tool call")
|
| 370 |
+
return []
|
| 371 |
+
|
| 372 |
+
print(f"π Got MCP result with keys: {list(result.keys()) if isinstance(result, dict) else 'Not dict'}")
|
| 373 |
+
|
| 374 |
+
# Extract challenge data (we know it's in structuredContent.data from debug)
|
| 375 |
+
challenge_data_list = []
|
| 376 |
+
|
| 377 |
+
if isinstance(result, dict):
|
| 378 |
+
# Primary location: structuredContent.data
|
| 379 |
+
if "structuredContent" in result:
|
| 380 |
+
structured = result["structuredContent"]
|
| 381 |
+
if isinstance(structured, dict) and "data" in structured:
|
| 382 |
+
challenge_data_list = structured["data"]
|
| 383 |
+
print(f"β
Found {len(challenge_data_list)} challenges in structuredContent.data")
|
| 384 |
|
| 385 |
+
# Fallback: direct data field
|
| 386 |
+
elif "data" in result:
|
| 387 |
+
challenge_data_list = result["data"]
|
| 388 |
+
print(f"β
Found {len(challenge_data_list)} challenges in data field")
|
| 389 |
+
|
| 390 |
+
if not challenge_data_list:
|
| 391 |
+
print("β No challenge data found in response")
|
| 392 |
+
return []
|
| 393 |
+
|
| 394 |
+
print(f"π― Processing {len(challenge_data_list)} raw challenges...")
|
| 395 |
+
|
| 396 |
+
# Convert to Challenge objects
|
| 397 |
+
challenges = []
|
| 398 |
+
for i, item in enumerate(challenge_data_list):
|
| 399 |
+
if isinstance(item, dict):
|
| 400 |
+
try:
|
| 401 |
+
challenge = self.convert_topcoder_challenge(item)
|
| 402 |
+
challenges.append(challenge)
|
| 403 |
+
|
| 404 |
+
# Show details for first challenge
|
| 405 |
+
if i == 0:
|
| 406 |
+
print(f"π Sample: {challenge.title} | {challenge.prize} | {challenge.technologies}")
|
| 407 |
+
|
| 408 |
+
except Exception as e:
|
| 409 |
+
print(f"β οΈ Error converting challenge {i}: {e}")
|
| 410 |
+
# Don't let one bad challenge break everything
|
| 411 |
+
continue
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 412 |
else:
|
| 413 |
+
print(f"β οΈ Unexpected challenge format at index {i}: {type(item)}")
|
| 414 |
|
| 415 |
+
print(f"π SUCCESSFULLY converted {len(challenges)} REAL challenges!")
|
| 416 |
+
|
| 417 |
+
# IMPORTANT: Always return challenges if we got any data at all
|
| 418 |
+
if len(challenges) > 0:
|
| 419 |
+
return challenges
|
| 420 |
+
else:
|
| 421 |
+
print("β No challenges could be converted from raw data")
|
| 422 |
+
return []
|
| 423 |
|
| 424 |
def calculate_advanced_compatibility_score(self, challenge: Challenge, user_profile: UserProfile, query: str) -> tuple:
|
| 425 |
score = 0.0
|