Last active
September 24, 2025 01:41
-
-
Save cheeseonamonkey/25a0f5e7d94bfefcb99c265fc79d7823 to your computer and use it in GitHub Desktop.
Get chess.com games of username
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // fetch archives of a username | |
| async function fetchUserArchives(username) { | |
| const url = `https://api.chess.com/pub/player/${username}/games/archives`; | |
| const response = await fetch(url); | |
| const data = await response.json(); | |
| return data.archives; | |
| } | |
| // fetch games from an archive | |
| async function fetchArchiveGames(username, month, year) { | |
| const archiveUrl = `https://api.chess.com/pub/player/${username}/games/${year}/${month}`; | |
| const response = await fetch(archiveUrl); | |
| const data = await response.json(); | |
| return data.games; | |
| } | |
| // fetch all games for an array of usernames | |
| async function fetchAllUsersGames(usernames) { | |
| const allGames = []; | |
| // for each username | |
| for (let username of usernames) { | |
| const archives = await fetchUserArchives(username); | |
| // for each archive of each user | |
| for (let archiveUrl of archives) { | |
| const parts = archiveUrl.split('/'); | |
| const year = parts[parts.length - 2]; | |
| const month = parts[parts.length - 1]; | |
| const games = await fetchArchiveGames(username, month, year); | |
| allGames.push(...games); | |
| } | |
| } | |
| return allGames; | |
| } | |
| module.exports = { | |
| fetchAllUsersGames | |
| } | |
| /* | |
| items in the array are like this: | |
| { | |
| "url": "https://www.chess.com/game/live/140932387438", | |
| "pgn": "[Event \"Live Chess\"]\n[Site \"Chess.com\"]\n[Date \"2025.07.21\"]\n[Round \"-\"]\n[White \"ffffattyyyy\"]\n[Black \"Darknight21060\"]\n[Result \"0-1\"]\n[CurrentPosition \"r1b1k1nr/ppp3pp/2np4/4p1q1/3P2P1/2N5/PPP1PP2/R2QKB1R w KQkq - 0 9\"]\n[Timezone \"UTC\"]\n[ECO \"A00\"]\n[ECOUrl \"https://www.chess.com/openings/Van-Geet-Opening-Reversed-Nimzowitsch-Napoleon-Attack\"]\n[UTCDate \"2025.07.21\"]\n[UTCTime \"07:35:13\"]\n[WhiteElo \"633\"]\n[BlackElo \"824\"]\n[TimeControl \"600\"]\n[Termination \"Darknight21060 won by resignation\"]\n[StartTime \"07:35:13\"]\n[EndDate \"2025.07.21\"]\n[EndTime \"07:36:50\"]\n[Link \"https://www.chess.com/game/live/140932387438\"]\n\n1. d4 {[%clk 0:09:57.2]} 1... Nc6 {[%clk 0:09:57.5]} 2. Nf3 {[%clk 0:09:48.4]} 2... e5 {[%clk 0:09:53.3]} 3. Nc3 {[%clk 0:09:41.3]} 3... d6 {[%clk 0:09:49.8]} 4. Bg5 {[%clk 0:09:35.6]} 4... Be7 {[%clk 0:09:47.3]} 5. h4 {[%clk 0:09:28.3]} 5... f6 {[%clk 0:09:46.1]} 6. g4 {[%clk 0:09:03.5]} 6... fxg5 {[%clk 0:09:43.8]} 7. hxg5 {[%clk 0:09:01.5]} 7... Bxg5 {[%clk 0:09:39.7]} 8. Nxg5 {[%clk 0:08:56]} 8... Qxg5 {[%clk 0:09:37.3]} 0-1\n", | |
| "time_control": "600", | |
| "end_time": 1753083410, | |
| "tcn": "lB5Qgv0KbsZRcM90pF1ToETMFM0MvM7M", | |
| "fen": "r1b1k1nr/ppp3pp/2np4/4p1q1/3P2P1/2N5/PPP1PP2/R2QKB1R w KQkq - 0 9", | |
| "time_class": "rapid", | |
| "white": { | |
| "rating": 633, | |
| "result": "resigned", | |
| "@id": "https://api.chess.com/pub/player/ffffattyyyy", | |
| "username": "ffffattyyyy", | |
| "uuid": "090b33d8-6605-11f0-a6b9-c7fb2182c58c" | |
| }, | |
| "black": { | |
| "rating": 824, | |
| "result": "win", | |
| "@id": "https://api.chess.com/pub/player/darknight21060", | |
| "username": "Darknight21060", | |
| "uuid": "a6147066-34a3-11ef-b208-83c070850c9b" | |
| }, | |
| "eco": "https://www.chess.com/openings/Van-Geet-Opening-Reversed-Nimzowitsch-Napoleon-Attack" | |
| } | |
| */ | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| const isUserWinner = (game, username) => | |
| (game.white.username === username && game.white.result === "win") || | |
| (game.black.username === username && game.black.result === "win"); | |
| const isUserWhite = (game, username) => (game.white.username === username); | |
| const isUserBlack = (game, username) => (!isUserWhite(game, username)); | |
| const turnCastled = (game, username) => { | |
| // | |
| }; | |
| const typeOfCastle = (game, username) => { | |
| // | |
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // Ripped off the Sunfish chess engine, modified it a bit, and converted to JS | |
| // https://github.com/thomasahle/sunfish | |
| #!/usr/bin/env python3 | |
| """ | |
| Simplified Chess Position Evaluator | |
| """ | |
| # Piece values | |
| piece = {"P": 100, "N": 281, "B": 319, "R": 479, "Q": 931, "K": 60000} | |
| # Piece-Square Tables - positional bonuses for each square (64 squares, a1-h8) | |
| PST = { | |
| 'P': [ 0, 0, 0, 0, 0, 0, 0, 0, # rank 1 (unused for pawns) | |
| 78, 83, 86, 73, 102, 82, 85, 90, # rank 2 | |
| 7, 29, 21, 44, 40, 31, 44, 7, # rank 3 | |
| -17, 16, -2, 15, 14, 0, 15, -13, # rank 4 | |
| -26, 3, 10, 9, 6, 1, 0, -23, # rank 5 | |
| -22, 9, 5, -11, -10, -2, 3, -19, # rank 6 | |
| -31, 8, -7, -37, -36, -14, 3, -31, # rank 7 | |
| 0, 0, 0, 0, 0, 0, 0, 0], # rank 8 (unused for pawns) | |
| 'N': [-66, -53, -75, -75, -10, -55, -58, -70, | |
| -3, -6, 100, -36, 4, 62, -4, -14, | |
| 10, 67, 1, 74, 73, 27, 62, -2, | |
| 24, 24, 45, 37, 33, 41, 25, 17, | |
| -1, 5, 31, 21, 22, 35, 2, 0, | |
| -18, 10, 13, 22, 18, 15, 11, -14, | |
| -23, -15, 2, 0, 2, 0, -23, -20, | |
| -74, -23, -26, -24, -19, -35, -22, -69], | |
| 'B': [-59, -78, -82, -76, -23,-107, -37, -50, | |
| -11, 20, 35, -42, -39, 31, 2, -22, | |
| -9, 39, -32, 41, 52, -10, 28, -14, | |
| 25, 17, 20, 34, 26, 25, 15, 10, | |
| 13, 10, 17, 23, 17, 16, 0, 7, | |
| 14, 25, 24, 15, 8, 25, 20, 15, | |
| 19, 20, 11, 6, 7, 6, 20, 16, | |
| -7, 2, -15, -12, -14, -15, -10, -10], | |
| 'R': [ 35, 29, 33, 4, 37, 33, 56, 50, | |
| 55, 29, 56, 67, 55, 62, 34, 60, | |
| 19, 35, 28, 33, 45, 27, 25, 15, | |
| 0, 5, 16, 13, 18, -4, -9, -6, | |
| -28, -35, -16, -21, -13, -29, -46, -30, | |
| -42, -28, -42, -25, -25, -35, -26, -46, | |
| -53, -38, -31, -26, -29, -43, -44, -53, | |
| -30, -24, -18, 5, -2, -18, -31, -32], | |
| 'Q': [ 6, 1, -8,-104, 69, 24, 88, 26, | |
| 14, 32, 60, -10, 20, 76, 57, 24, | |
| -2, 43, 32, 60, 72, 63, 43, 2, | |
| 1, -16, 22, 17, 25, 20, -13, -6, | |
| -14, -15, -2, -5, -1, -10, -20, -22, | |
| -30, -6, -13, -11, -16, -11, -16, -27, | |
| -36, -18, 0, -19, -15, -15, -21, -38, | |
| -39, -30, -31, -13, -31, -36, -34, -42], | |
| 'K': [ 4, 54, 47, -99, -99, 60, 83, -62, | |
| -32, 10, 55, 56, 56, 55, 10, 3, | |
| -62, 12, -57, 44, -67, 28, 37, -31, | |
| -55, 50, 11, -4, -19, 13, 0, -49, | |
| -55, -43, -52, -28, -51, -47, -8, -50, | |
| -47, -42, -43, -79, -64, -32, -29, -32, | |
| -4, 3, -14, -50, -57, -18, 13, 4, | |
| 17, 30, -3, -14, 6, -1, 40, 18], | |
| } | |
| def fen_to_board(fen): | |
| """Convert FEN to 8x8 board array.""" | |
| board = [] | |
| ranks = fen.split('/') | |
| for rank in ranks: | |
| row = [] | |
| for char in rank: | |
| if char.isdigit(): | |
| row.extend(['.'] * int(char)) # Empty squares | |
| else: | |
| row.append(char) # Piece | |
| board.append(row) | |
| return board | |
| def evaluate_position(fen): | |
| """ | |
| Evaluate position from FEN notation. | |
| Args: | |
| fen: FEN string (position part only) | |
| Returns: | |
| dict: {'material': {'white': int, 'black': int, 'balance': int}, | |
| 'positional': {'white': int, 'black': int, 'balance': int}, | |
| 'total': {'white': int, 'black': int, 'balance': int}} | |
| """ | |
| board = fen_to_board(fen) | |
| white_material = black_material = 0 | |
| white_positional = black_positional = 0 | |
| for rank in range(8): | |
| for file in range(8): | |
| piece = board[rank][file] | |
| if piece == '.': | |
| continue | |
| square_index = rank * 8 + file | |
| piece_type = piece.upper() | |
| if piece_type in PIECE_VALUES: | |
| piece_value = PIECE_VALUES[piece_type] | |
| positional_value = PST[piece_type][square_index] | |
| if piece.isupper(): # White piece | |
| white_material += piece_value | |
| white_positional += positional_value | |
| else: # Black piece (flip board for positional evaluation) | |
| black_material += piece_value | |
| # Black pieces use flipped board perspective | |
| flipped_square = (7 - rank) * 8 + file | |
| black_positional += PST[piece_type][flipped_square] | |
| material_balance = white_material - black_material | |
| positional_balance = white_positional - black_positional | |
| total_white = white_material + white_positional | |
| total_black = black_material + black_positional | |
| return { | |
| 'material': { | |
| 'white': white_material, | |
| 'black': black_material, | |
| 'balance': material_balance | |
| }, | |
| 'positional': { | |
| 'white': white_positional, | |
| 'black': black_positional, | |
| 'balance': positional_balance | |
| }, | |
| 'total': { | |
| 'white': total_white, | |
| 'black': total_black, | |
| 'balance': total_white - total_black | |
| } | |
| } | |
| # Example usage | |
| if __name__ == "__main__": | |
| # Starting position | |
| start_fen = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR" | |
| print("Chess Position Evaluation:") | |
| print("=" * 40) | |
| result = evaluate_position(start_fen) | |
| print(f"Material - White: {result['material']['white']:4d}, Black: {result['material']['black']:4d}, Balance: {result['material']['balance']:4d}") | |
| print(f"Positional - White: {result['positional']['white']:4d}, Black: {result['positional']['black']:4d}, Balance: {result['positional']['balance']:4d}") | |
| print(f"Total - White: {result['total']['white']:4d}, Black: {result['total']['black']:4d}, Balance: {result['total']['balance']:4d}") | |
| print("\nPiece Values:") | |
| for piece, value in PIECE_VALUES.items(): | |
| print(f" {piece}: {value}") | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment