budanalytics's picture
Update app.py
2b601d7 verified
Raw
History Blame Contribute Delete
8 kB
import streamlit as st
st.set_page_config(page_title="Chess Openings Suggestion Tool", layout="wide")
import requests
import os
from bs4 import BeautifulSoup
# Configure OpenAI API (using OPENAI_API_KEY)
OPENAI_API_KEY = os.getenv("ChessOpeningKey")
OPENAI_ENDPOINT = "https://api.openai.com/v1/chat/completions"
def fetch_opening_data(opening_name):
"""Fetches additional information about a specific chess opening."""
if not opening_name:
return None
try:
# Format the opening name for URL
formatted_name = opening_name.replace(" ", "_")
url = f"https://en.wikipedia.org/wiki/{formatted_name}"
response = requests.get(url, timeout=10)
if response.status_code != 200:
# Try chess-specific sites as fallback
url = f"https://www.chess.com/openings/{formatted_name}"
response = requests.get(url, timeout=10)
if response.status_code == 200:
soup = BeautifulSoup(response.content, "html.parser")
content = []
# Extract text from p tags (paragraphs)
paragraphs = soup.find_all('p')
for p in paragraphs[:5]: # Limit to first 5 paragraphs
text = p.get_text(strip=True)
if text and len(text) > 50: # Only meaningful paragraphs
content.append(text)
return "\n\n".join(content[:3]) # Return first 3 substantial paragraphs
else:
return "No additional information available for this opening."
except Exception as e:
st.error(f"Error fetching opening data: {str(e)}")
return "Failed to retrieve opening information."
def generate_chess_openings(player_info):
"""Generates chess opening recommendations based on player preferences."""
prompt = f"""As a chess opening specialist and grandmaster, recommend personalized chess openings for a player with the following preferences:
{player_info}
Your recommendations should include:
1. **White Openings:** Recommend exactly 3 openings to study when playing White that match the player's style and first move preferences.
2. **Black Openings:** Recommend exactly 3 openings to study when playing Black that match the player's style.
For each opening recommendation, include:
- Full name of the opening
- Most common lines stemming from the opening(4-8 moves)
- Famous players who use/used this opening
- Key concepts to master first
- Common traps or tactical motifs to be aware of
- Why this opening suits the player's described style
Format your response in clear markdown with headers and bullet points. Structure it with White openings first, followed by Black openings."""
headers = {
"Authorization": f"Bearer {OPENAI_API_KEY}",
"Content-Type": "application/json"
}
data = {
"model": "gpt-3.5-turbo",
"messages": [
{"role": "system", "content": "You are a chess grandmaster specializing in chess openings and teaching players how to expand their opening repertoire."},
{"role": "user", "content": prompt}
],
"temperature": 0.7,
"max_tokens": 2000
}
try:
response = requests.post(OPENAI_ENDPOINT, json=data, headers=headers)
response.raise_for_status()
return response.json()["choices"][0]["message"]["content"]
except Exception as e:
st.error(f"API Error: {str(e)}")
return None
# Chess style descriptions for the dropdown
chess_styles = {
"Aggressive": "Prefer direct attacks, sacrifices, and tactical complications",
"Positional": "Focus on long-term strategic advantages, piece placement, and structure",
"Defensive": "Excel at holding positions, counterattacking, and resource-finding",
"Tactical": "Enjoy combinations, calculations, and complex positions",
"Dynamic": "Like imbalanced positions with active piece play",
"Classical": "Prefer solid development and fundamental principles",
"Hypermodern": "Control the center with pieces rather than pawns"
}
# Define common first moves with descriptions
first_moves = {
"e4": "Open, tactical games with immediate center control",
"d4": "More closed, positional games with solid structure",
"c4": "Flexible flank opening with transpositional possibilities",
"Nf3": "Hypermodern approach controlling center from distance"
}
# Streamlit UI
st.title("♟️ Chess Openings Suggestion Tool")
st.markdown("### Get personalized chess opening recommendations based on your preferences and style.")
# Player info collection
st.markdown("## Your Chess Profile")
rating = st.select_slider(
"Your approximate rating level",
options=["Beginner (<1000)", "Advanced Beginner (1000-1200)", "Novice (1200-1400)", "Intermediate (1400-1600)", "Seasoned Player (1600-1800)", "Advanced (1800-2000)", "Master (2000+)"]
)
playing_style = st.selectbox(
"Your preferred playing style",
options=list(chess_styles.keys()),
format_func=lambda x: f"{x} - {chess_styles[x]}"
)
# Changed from selectbox to multiselect
preferred_first_moves = st.multiselect(
"Your preferred first moves as White (select one or more)",
options=list(first_moves.keys()),
default=[list(first_moves.keys())[0]], # Default to e4
format_func=lambda x: f"{x} - {first_moves[x]}"
)
current_openings = st.text_area(
"Openings you currently play (optional)",
help="List any chess openings you already play and are comfortable with."
)
time_control = st.radio(
"Preferred time control",
["Bullet/Blitz", "Rapid", "Classical"]
)
improvement_goals = st.multiselect(
"What aspects of your chess would you like to improve?",
["Tactical vision", "Strategic understanding", "Endgame technique",
"Opening theory", "Time management", "Calculation ability"]
)
specific_requests = st.text_area(
"Any specific requirements or preferences? (optional)",
help="E.g., 'I want openings that lead to open positions' or 'I prefer solid, low-risk openings'"
)
if st.button("Generate Opening Recommendations"):
if not preferred_first_moves:
st.warning("Please select at least one preferred first move.")
else:
with st.spinner("Analyzing your chess profile and finding suitable openings..."):
# Format preferred first moves for the prompt
formatted_moves = ", ".join([move.split(" (")[0] for move in preferred_first_moves])
player_info = f"""
Rating Level: {rating}
Playing Style: {playing_style}
Preferred First Moves as White: {formatted_moves}
Current Openings: {current_openings if current_openings else 'Not provided'}
Time Control Preference: {time_control}
Improvement Goals: {', '.join(improvement_goals) if improvement_goals else 'Not specified'}
Specific Requirements: {specific_requests if specific_requests else 'None provided'}
"""
recommendations = generate_chess_openings(player_info)
if recommendations:
st.markdown(recommendations)
# Add an option to explore a specific opening in more detail
st.markdown("---")
st.markdown("## Explore an Opening Further")
opening_to_explore = st.text_input("Enter the name of an opening to get more details:",
help="Type the full name of one of the recommended openings")
if opening_to_explore and st.button("Get Details"):
with st.spinner(f"Fetching additional information about {opening_to_explore}..."):
opening_details = fetch_opening_data(opening_to_explore)
if opening_details:
st.markdown(f"### {opening_to_explore} - Additional Information")
st.markdown(opening_details)