Skip to content

Instantly share code, notes, and snippets.

@cheeseonamonkey
Last active September 24, 2025 01:41
Show Gist options
  • Select an option

  • Save cheeseonamonkey/25a0f5e7d94bfefcb99c265fc79d7823 to your computer and use it in GitHub Desktop.

Select an option

Save cheeseonamonkey/25a0f5e7d94bfefcb99c265fc79d7823 to your computer and use it in GitHub Desktop.
Get chess.com games of username
// 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"
}
*/
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) => {
//
};
// 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