Abdelkarim Bengrine commited on
Commit
d08b8f9
·
1 Parent(s): f434338

fix: deployment

Browse files
Files changed (1) hide show
  1. echo_server.py +129 -9
echo_server.py CHANGED
@@ -8,6 +8,7 @@ from typing import List, Tuple, defaultdict, Dict
8
  from dataclasses import dataclass
9
  import io
10
 
 
11
  @dataclass
12
  class CoachNote:
13
  move_no: int
@@ -592,7 +593,9 @@ def _identify_patterns(notes: List[CoachNote]) -> List[MistakePattern]:
592
  mcp = FastMCP(name="EchoServer", stateless_http=True)
593
 
594
 
595
- @mcp.tool(description="Analyze all games from the last 30 days and return behavioral patterns")
 
 
596
  def get_monthly_analysis(
597
  username: str, depth: int = 12, max_games: int = 20
598
  ) -> List[Dict]:
@@ -626,9 +629,7 @@ def get_monthly_analysis(
626
  for i, pgn in enumerate(pgns):
627
  print(f"Analyzing game {i+1}/{len(pgns)}...")
628
  try:
629
- notes = analyze_pgn_with_stockfish(
630
- pgn, depth=depth
631
- )
632
  all_notes.extend(notes)
633
  except Exception as e:
634
  print(f"Error analyzing game {i+1}: {e}")
@@ -651,7 +652,9 @@ def get_monthly_analysis(
651
  ]
652
 
653
 
654
- @mcp.tool(description="Analyze a single game and return detailed human-readable feedback")
 
 
655
  def get_human_feedback(pgn_text: str, depth: int = 16) -> List[Dict]:
656
  """
657
  Analyze a single game and return detailed human-readable feedback.
@@ -693,10 +696,10 @@ def get_human_feedback(pgn_text: str, depth: int = 16) -> List[Dict]:
693
  ]
694
 
695
 
696
- @mcp.tool(description="Analyze a single game and return classic chess.com style analysis")
697
- def get_classic_analysis(
698
- pgn_text: str, depth: int = 16
699
- ) -> List[Dict]:
700
  """
701
  Analyze a single game and return classic chess.com style analysis.
702
 
@@ -751,6 +754,123 @@ def get_classic_analysis(
751
  return classic_analysis
752
 
753
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
754
  @mcp.tool(description="Fetch and analyze the most recent finished game for a user")
755
  def get_latest_game_analysis(username: str, depth: int = 16) -> Dict:
756
  """
 
8
  from dataclasses import dataclass
9
  import io
10
 
11
+
12
  @dataclass
13
  class CoachNote:
14
  move_no: int
 
593
  mcp = FastMCP(name="EchoServer", stateless_http=True)
594
 
595
 
596
+ @mcp.tool(
597
+ description="Analyze all games from the last 30 days and return behavioral patterns"
598
+ )
599
  def get_monthly_analysis(
600
  username: str, depth: int = 12, max_games: int = 20
601
  ) -> List[Dict]:
 
629
  for i, pgn in enumerate(pgns):
630
  print(f"Analyzing game {i+1}/{len(pgns)}...")
631
  try:
632
+ notes = analyze_pgn_with_stockfish(pgn, depth=depth)
 
 
633
  all_notes.extend(notes)
634
  except Exception as e:
635
  print(f"Error analyzing game {i+1}: {e}")
 
652
  ]
653
 
654
 
655
+ @mcp.tool(
656
+ description="Analyze a single game and return detailed human-readable feedback"
657
+ )
658
  def get_human_feedback(pgn_text: str, depth: int = 16) -> List[Dict]:
659
  """
660
  Analyze a single game and return detailed human-readable feedback.
 
696
  ]
697
 
698
 
699
+ @mcp.tool(
700
+ description="Analyze a single game and return classic chess.com style analysis"
701
+ )
702
+ def get_classic_analysis(pgn_text: str, depth: int = 16) -> List[Dict]:
703
  """
704
  Analyze a single game and return classic chess.com style analysis.
705
 
 
754
  return classic_analysis
755
 
756
 
757
+ import requests
758
+ import re
759
+ import json
760
+ from typing import List, Dict
761
+ from bs4 import BeautifulSoup
762
+
763
+
764
+ def _fetch_tournaments_page() -> str:
765
+ """Fetch the raw content from the chess tournaments page."""
766
+ url = "https://www.echecsfrance.com/en/tournaments"
767
+ try:
768
+ response = requests.get(url)
769
+ response.raise_for_status()
770
+ return response.text
771
+ except requests.RequestException as e:
772
+ print(f"Error fetching the page: {e}")
773
+ return ""
774
+
775
+
776
+ def _extract_tournament_references(html_content: str) -> List[str]:
777
+ """Extract all FicheTournoi.aspx?Ref=XXXXX patterns from HTML."""
778
+ # Regex pattern to match FicheTournoi.aspx?Ref= followed by digits
779
+ pattern = r"FicheTournoi\.aspx\?Ref=\d+"
780
+
781
+ # Find all matches
782
+ matches = re.findall(pattern, html_content)
783
+
784
+ # Remove duplicates while preserving order
785
+ unique_matches = list(dict.fromkeys(matches))
786
+
787
+ return unique_matches
788
+
789
+
790
+ def _fetch_tournament_details(tournament_ref: str) -> Dict[str, str]:
791
+ """Fetch tournament details from a specific tournament page."""
792
+ base_url = "https://www.echecs.asso.fr/"
793
+ full_url = base_url + tournament_ref
794
+
795
+ try:
796
+ response = requests.get(full_url)
797
+ response.raise_for_status()
798
+
799
+ soup = BeautifulSoup(response.text, "html.parser")
800
+
801
+ def extract_field(field_id: str) -> str:
802
+ """Helper function to extract field value by ID."""
803
+ elem = soup.find("span", {"id": field_id})
804
+ return elem.get_text().strip() if elem else "N/A"
805
+
806
+ # Extract all requested fields
807
+ details = {
808
+ "name": extract_field("ctl00_ContentPlaceHolderMain_LabelNom"),
809
+ "dates": extract_field("ctl00_ContentPlaceHolderMain_LabelDates"),
810
+ "nombre_rondes": extract_field(
811
+ "ctl00_ContentPlaceHolderMain_LabelNbrRondes"
812
+ ),
813
+ "cadence": extract_field("ctl00_ContentPlaceHolderMain_LabelCadence"),
814
+ "organisateur": extract_field(
815
+ "ctl00_ContentPlaceHolderMain_LabelOrganisateur"
816
+ ),
817
+ "arbitre": extract_field("ctl00_ContentPlaceHolderMain_LabelArbitre"),
818
+ "adresse": extract_field("ctl00_ContentPlaceHolderMain_LabelAdresse"),
819
+ "contact": extract_field("ctl00_ContentPlaceHolderMain_LabelContact"),
820
+ "premier_prix": extract_field("ctl00_ContentPlaceHolderMain_LabelPrix1"),
821
+ "inscription_senior": extract_field(
822
+ "ctl00_ContentPlaceHolderMain_LabelInscriptionSenior"
823
+ ),
824
+ "inscription_jeunes": extract_field(
825
+ "ctl00_ContentPlaceHolderMain_LabelInscriptionJeune"
826
+ ),
827
+ "annonce": extract_field("ctl00_ContentPlaceHolderMain_LabelAnnonce"),
828
+ "url": full_url,
829
+ }
830
+
831
+ return details
832
+ except requests.RequestException as e:
833
+ print(f"Error fetching tournament {tournament_ref}: {e}")
834
+ return {
835
+ "name": "Error",
836
+ "dates": "Error",
837
+ "nombre_rondes": "Error",
838
+ "cadence": "Error",
839
+ "organisateur": "Error",
840
+ "arbitre": "Error",
841
+ "adresse": "Error",
842
+ "contact": "Error",
843
+ "premier_prix": "Error",
844
+ "inscription_senior": "Error",
845
+ "inscription_jeunes": "Error",
846
+ "annonce": "Error",
847
+ "url": full_url,
848
+ }
849
+
850
+
851
+ @mcp.tool(description="Get the latest tournaments data")
852
+ def get_tournaments_data():
853
+ html_content = _fetch_tournaments_page()
854
+
855
+ if not html_content:
856
+ return {"total_tournaments": 0, "tournaments": []}
857
+
858
+ tournament_refs = _extract_tournament_references(html_content)
859
+
860
+ tournament_details = []
861
+
862
+ for ref in tournament_refs:
863
+ details = _fetch_tournament_details(ref)
864
+ tournament_details.append(details)
865
+
866
+ result = {
867
+ "total_tournaments": len(tournament_details),
868
+ "tournaments": tournament_details,
869
+ }
870
+
871
+ return result
872
+
873
+
874
  @mcp.tool(description="Fetch and analyze the most recent finished game for a user")
875
  def get_latest_game_analysis(username: str, depth: int = 16) -> Dict:
876
  """