budanalytics/Chess_Openings_Suggester
0
1import streamlit as st2st.set_page_config(page_title="Chess Openings Suggestion Tool", layout="wide")3 4import requests5import os6from bs4 import BeautifulSoup7 8# Configure OpenAI API (using OPENAI_API_KEY)9OPENAI_API_KEY = os.getenv("ChessOpeningKey")10OPENAI_ENDPOINT = "https://api.openai.com/v1/chat/completions"11 12def fetch_opening_data(opening_name):13 """Fetches additional information about a specific chess opening."""14 if not opening_name:15 return None16 17 try:18 # Format the opening name for URL19 formatted_name = opening_name.replace(" ", "_")20 url = f"https://en.wikipedia.org/wiki/{formatted_name}"21 22 response = requests.get(url, timeout=10)23 if response.status_code != 200:24 # Try chess-specific sites as fallback25 url = f"https://www.chess.com/openings/{formatted_name}"26 response = requests.get(url, timeout=10)27 28 if response.status_code == 200:29 soup = BeautifulSoup(response.content, "html.parser")30 31 content = []32 # Extract text from p tags (paragraphs)33 paragraphs = soup.find_all('p')34 for p in paragraphs[:5]: # Limit to first 5 paragraphs35 text = p.get_text(strip=True)36 if text and len(text) > 50: # Only meaningful paragraphs37 content.append(text)38 39 return "\n\n".join(content[:3]) # Return first 3 substantial paragraphs40 else:41 return "No additional information available for this opening."42 except Exception as e:43 st.error(f"Error fetching opening data: {str(e)}")44 return "Failed to retrieve opening information."45 46def generate_chess_openings(player_info):47 """Generates chess opening recommendations based on player preferences."""48 prompt = f"""As a chess opening specialist and grandmaster, recommend personalized chess openings for a player with the following preferences:49{player_info}50 51Your recommendations should include:52 531. **White Openings:** Recommend exactly 3 openings to study when playing White that match the player's style and first move preferences.54 552. **Black Openings:** Recommend exactly 3 openings to study when playing Black that match the player's style.56 57For each opening recommendation, include:58 - Full name of the opening59 - Most common lines stemming from the opening(4-8 moves)60 - Famous players who use/used this opening61 - Key concepts to master first62 - Common traps or tactical motifs to be aware of63 - Why this opening suits the player's described style64 65Format your response in clear markdown with headers and bullet points. Structure it with White openings first, followed by Black openings."""66 67 headers = {68 "Authorization": f"Bearer {OPENAI_API_KEY}",69 "Content-Type": "application/json"70 }71 72 data = {73 "model": "gpt-3.5-turbo",74 "messages": [75 {"role": "system", "content": "You are a chess grandmaster specializing in chess openings and teaching players how to expand their opening repertoire."},76 {"role": "user", "content": prompt}77 ],78 "temperature": 0.7,79 "max_tokens": 200080}81 82 83 try:84 response = requests.post(OPENAI_ENDPOINT, json=data, headers=headers)85 response.raise_for_status()86 return response.json()["choices"][0]["message"]["content"]87 except Exception as e:88 st.error(f"API Error: {str(e)}")89 return None90 91# Chess style descriptions for the dropdown92chess_styles = {93 "Aggressive": "Prefer direct attacks, sacrifices, and tactical complications",94 "Positional": "Focus on long-term strategic advantages, piece placement, and structure",95 "Defensive": "Excel at holding positions, counterattacking, and resource-finding",96 "Tactical": "Enjoy combinations, calculations, and complex positions",97 "Dynamic": "Like imbalanced positions with active piece play",98 "Classical": "Prefer solid development and fundamental principles",99 "Hypermodern": "Control the center with pieces rather than pawns"100}101 102# Define common first moves with descriptions103first_moves = {104 "e4": "Open, tactical games with immediate center control",105 "d4": "More closed, positional games with solid structure",106 "c4": "Flexible flank opening with transpositional possibilities",107 "Nf3": "Hypermodern approach controlling center from distance"108}109 110 111# Streamlit UI112st.title("♟️ Chess Openings Suggestion Tool")113st.markdown("### Get personalized chess opening recommendations based on your preferences and style.")114 115# Player info collection116st.markdown("## Your Chess Profile")117 118rating = st.select_slider(119 "Your approximate rating level",120 options=["Beginner (<1000)", "Advanced Beginner (1000-1200)", "Novice (1200-1400)", "Intermediate (1400-1600)", "Seasoned Player (1600-1800)", "Advanced (1800-2000)", "Master (2000+)"]121)122 123playing_style = st.selectbox(124 "Your preferred playing style",125 options=list(chess_styles.keys()),126 format_func=lambda x: f"{x} - {chess_styles[x]}"127)128 129# Changed from selectbox to multiselect130preferred_first_moves = st.multiselect(131 "Your preferred first moves as White (select one or more)",132 options=list(first_moves.keys()),133 default=[list(first_moves.keys())[0]], # Default to e4134 format_func=lambda x: f"{x} - {first_moves[x]}"135)136 137current_openings = st.text_area(138 "Openings you currently play (optional)",139 help="List any chess openings you already play and are comfortable with."140)141 142time_control = st.radio(143 "Preferred time control",144 ["Bullet/Blitz", "Rapid", "Classical"]145)146 147improvement_goals = st.multiselect(148 "What aspects of your chess would you like to improve?",149 ["Tactical vision", "Strategic understanding", "Endgame technique", 150 "Opening theory", "Time management", "Calculation ability"]151)152 153specific_requests = st.text_area(154 "Any specific requirements or preferences? (optional)",155 help="E.g., 'I want openings that lead to open positions' or 'I prefer solid, low-risk openings'"156)157 158if st.button("Generate Opening Recommendations"):159 if not preferred_first_moves:160 st.warning("Please select at least one preferred first move.")161 else:162 with st.spinner("Analyzing your chess profile and finding suitable openings..."):163 # Format preferred first moves for the prompt164 formatted_moves = ", ".join([move.split(" (")[0] for move in preferred_first_moves])165 166 player_info = f"""167Rating Level: {rating}168Playing Style: {playing_style}169Preferred First Moves as White: {formatted_moves}170Current Openings: {current_openings if current_openings else 'Not provided'}171Time Control Preference: {time_control}172Improvement Goals: {', '.join(improvement_goals) if improvement_goals else 'Not specified'}173Specific Requirements: {specific_requests if specific_requests else 'None provided'}174"""175 recommendations = generate_chess_openings(player_info)176 if recommendations:177 st.markdown(recommendations)178 179 # Add an option to explore a specific opening in more detail180 st.markdown("---")181 st.markdown("## Explore an Opening Further")182 opening_to_explore = st.text_input("Enter the name of an opening to get more details:",183 help="Type the full name of one of the recommended openings")184 185 if opening_to_explore and st.button("Get Details"):186 with st.spinner(f"Fetching additional information about {opening_to_explore}..."):187 opening_details = fetch_opening_data(opening_to_explore)188 if opening_details:189 st.markdown(f"### {opening_to_explore} - Additional Information")190 st.markdown(opening_details)191 