File size: 7,998 Bytes
cac9eab 1948b29 56af34b bc46207 7409805 1d72d1e 24b72ba 56af34b b04843f dbfa8c2 68833e7 1948b29 51ff7fb 1d72d1e 1948b29 1d72d1e 1948b29 56af34b 1948b29 1d72d1e 1948b29 1d72d1e 1948b29 56af34b 1948b29 2830071 1948b29 21af56d 1948b29 2830071 b5df9d3 1d72d1e 56af34b 1d72d1e 2b601d7 1d72d1e dbfa8c2 1d72d1e 1948b29 e221385 1948b29 e221385 1d72d1e 1948b29 1d72d1e 1948b29 1d72d1e 1948b29 21af56d 1948b29 2830071 1948b29 2830071 1948b29 2830071 1948b29 2830071 1948b29 56af34b 2830071 48078ac | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 | 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)
|