@@ -151,105 +151,87 @@ function App() {
151151
152152 // Cache to prevent duplicate API calls (chess-api.com has 1000 calls/IP limit)
153153 const evalCacheRef = useRef ( new Map ( ) ) ;
154- const proxyIndexRef = useRef ( 0 ) ;
155- const rateLimitedRef = useRef ( false ) ;
154+ const useFallbackRef = useRef ( false ) ;
156155
157- const fetchEvaluation = async ( fen , retryCount = 0 ) => {
158- // Check cache first to avoid duplicate calls
159- if ( evalCacheRef . current . has ( fen ) ) {
160- return evalCacheRef . current . get ( fen ) ;
161- }
162-
163- const endpoint = 'https://chess-api.com/v1' ;
164-
165- // CORS proxies to rotate through when rate limited
166- const corsProxies = [
167- null , // Direct request first
168- 'https://corsproxy.io/?' ,
169- 'https://api.allorigins.win/raw?url=' ,
170- 'https://cors-anywhere.herokuapp.com/' ,
171- ] ;
156+ const fetchFromChessApi = async ( fen ) => {
157+ const response = await fetch ( 'https://chess-api.com/v1' , {
158+ method : 'POST' ,
159+ headers : { 'Content-Type' : 'application/json' } ,
160+ body : JSON . stringify ( { fen, depth : 12 , maxThinkingTime : 50 } ) ,
161+ } ) ;
172162
173- const makeRequest = async ( proxyUrl ) => {
174- const targetUrl = proxyUrl ? `${ proxyUrl } ${ encodeURIComponent ( endpoint ) } ` : endpoint ;
175-
176- const response = await fetch ( targetUrl , {
177- method : 'POST' ,
178- headers : {
179- 'Content-Type' : 'application/json' ,
180- } ,
181- body : JSON . stringify ( {
182- fen : fen ,
183- depth : 12 ,
184- maxThinkingTime : 50 ,
185- } ) ,
186- } ) ;
163+ if ( response . status === 429 ) {
164+ throw new Error ( 'RATE_LIMITED' ) ;
165+ }
166+ if ( ! response . ok ) {
167+ throw new Error ( `chess-api.com failed: ${ response . status } ` ) ;
168+ }
187169
188- return response ;
170+ const data = await response . json ( ) ;
171+ return {
172+ evaluation : data . mate !== null ? ( data . mate > 0 ? 100 : - 100 ) : data . eval ,
173+ bestMove : data . san || data . move || null ,
174+ mate : data . mate ,
175+ depth : data . depth ,
176+ winChance : data . winChance ,
189177 } ;
178+ } ;
190179
191- try {
192- // Start with current proxy index (remembers if we're rate limited)
193- let response = await makeRequest ( corsProxies [ proxyIndexRef . current ] ) ;
194-
195- // Handle rate limiting (429) or other errors - try next proxy
196- if ( response . status === 429 || ! response . ok ) {
197- rateLimitedRef . current = true ;
198-
199- // Try each proxy until one works
200- for ( let i = 1 ; i < corsProxies . length && ! response . ok ; i ++ ) {
201- proxyIndexRef . current = i ;
202- console . log ( `Rate limited, trying proxy ${ i } ...` ) ;
203-
204- // Small delay before retry
205- await new Promise ( resolve => setTimeout ( resolve , 500 * i ) ) ;
206-
207- try {
208- response = await makeRequest ( corsProxies [ i ] ) ;
209- if ( response . ok ) break ;
210- } catch ( e ) {
211- console . log ( `Proxy ${ i } failed:` , e . message ) ;
212- }
213- }
214- }
180+ const fetchFromFallback = async ( fen ) => {
181+ const encodedFen = encodeURIComponent ( fen ) ;
182+ const response = await fetch ( `https://eval.plc.hadron43.in/eval-bars/?fen=${ encodedFen } ` ) ;
215183
216- if ( ! response . ok ) {
217- throw new Error ( `All endpoints failed (status : ${ response . status } ) ` ) ;
218- }
184+ if ( ! response . ok ) {
185+ throw new Error ( `Fallback API failed: ${ response . status } ` ) ;
186+ }
219187
220- const data = await response . json ( ) ;
188+ const data = await response . json ( ) ;
189+ return {
190+ evaluation : data . evaluation ,
191+ bestMove : null ,
192+ } ;
193+ } ;
221194
222- // chess-api.com response format:
223- // { eval: number, move: string, san: string, mate: number|null, centipawns: string, ... }
224- const result = {
225- evaluation : data . mate !== null ? ( data . mate > 0 ? 100 : - 100 ) : data . eval ,
226- bestMove : data . san || data . move || null ,
227- mate : data . mate ,
228- depth : data . depth ,
229- winChance : data . winChance ,
230- } ;
195+ const fetchEvaluation = async ( fen ) => {
196+ // Check cache first to avoid duplicate calls
197+ if ( evalCacheRef . current . has ( fen ) ) {
198+ return evalCacheRef . current . get ( fen ) ;
199+ }
231200
232- // Cache the result
233- evalCacheRef . current . set ( fen , result ) ;
201+ let result ;
234202
235- // Limit cache size to prevent memory issues (keep last 500 positions)
236- if ( evalCacheRef . current . size > 500 ) {
237- const firstKey = evalCacheRef . current . keys ( ) . next ( ) . value ;
238- evalCacheRef . current . delete ( firstKey ) ;
203+ try {
204+ // If we've been rate limited before, go straight to fallback
205+ if ( useFallbackRef . current ) {
206+ result = await fetchFromFallback ( fen ) ;
207+ } else {
208+ result = await fetchFromChessApi ( fen ) ;
239209 }
240-
241- return result ;
242210 } catch ( error ) {
243- console . error ( "Failed to fetch evaluation:" , error ) ;
211+ // On rate limit or failure, try fallback API
212+ if ( error . message === 'RATE_LIMITED' ) {
213+ console . log ( 'Rate limited on chess-api.com, switching to fallback API' ) ;
214+ useFallbackRef . current = true ;
215+ }
244216
245- // Retry once with exponential backoff
246- if ( retryCount < 2 ) {
247- await new Promise ( resolve => setTimeout ( resolve , 1000 * ( retryCount + 1 ) ) ) ;
248- return fetchEvaluation ( fen , retryCount + 1 ) ;
217+ try {
218+ result = await fetchFromFallback ( fen ) ;
219+ } catch ( fallbackError ) {
220+ console . error ( 'Both APIs failed:' , error . message , fallbackError . message ) ;
221+ throw fallbackError ;
249222 }
223+ }
250224
251- throw error ;
225+ // Cache the result
226+ evalCacheRef . current . set ( fen , result ) ;
227+
228+ // Limit cache size to prevent memory issues (keep last 500 positions)
229+ if ( evalCacheRef . current . size > 500 ) {
230+ const firstKey = evalCacheRef . current . keys ( ) . next ( ) . value ;
231+ evalCacheRef . current . delete ( firstKey ) ;
252232 }
233+
234+ return result ;
253235 } ;
254236 const handleRemoveLink = ( index ) => {
255237 setLinks ( ( prevLinks ) => prevLinks . filter ( ( link , i ) => i !== index ) ) ;
0 commit comments