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)