Skip to content

Instantly share code, notes, and snippets.

@neopunisher
Last active March 15, 2025 20:07
Show Gist options
  • Save neopunisher/a0ea9c46ef58624b0002729d948dd896 to your computer and use it in GitHub Desktop.
Save neopunisher/a0ea9c46ef58624b0002729d948dd896 to your computer and use it in GitHub Desktop.
https://www.word-battle.com/ unofficial api and helper tools; vibe coded with love
const endpoint = "https://htbgzenw76.execute-api.us-east-1.amazonaws.com/dev/app";
const callApi = async (funcName, data) => {
const response = await fetch(endpoint, {
body: JSON.stringify({ funcName, data }),
method: "POST",
headers: { "Content-Type": "application/json" }
});
if (!response.ok) {
throw new Error(`API call failed: ${response.status} ${response.statusText}`);
}
return response.json();
};
const createApiFunction = (funcName, argNames) => {
return async (...args) => {
if (args.length !== argNames.length) {
throw new Error(`Expected ${argNames.length} arguments, got ${args.length}`);
}
const data = Object.fromEntries(argNames.map((name, i) => [name, args[i]]));
return await callApi(funcName, data);
};
};
const register = createApiFunction("REGISTER_USER", ["username", "word"]);
const battle = createApiFunction("BATTLE", ["uuid"]);
const topPlayers = createApiFunction("LIST_TOP_USERS",[]);
const stats = async () => {
try {
window.players = (await topPlayers()).userRecords;
} catch (error) {
console.error('Failed to load player stats:', error);
}
};
// Global variables
window.battleId = '3f980ee9-f0b3-4437-9ccb-b4f786726b47';
window.running = false;
// Battle loop function
const runBattles = async () => {
if (window.running) return; // Prevent multiple loops from starting
window.running = true;
while (window.running) {
window.carterData.incrementBattle(window.battleId);
let { eloChange, message } = await battle(window.battleId);
console.log(eloChange, message);
await new Promise(resolve => setTimeout(resolve, 1000)); // Optional delay
}
console.log("Battle loop stopped.");
};
// Function to start the battle loop
window.startBattles = () => {
if (!window.running) {
console.log("Starting battle loop...");
runBattles();
} else {
console.log("Battle loop is already running.");
}
};
window.carterData = {};
window.carterData.battleCounts = window.carterData.battleCounts || {};
// Create increment function
window.carterData.incrementBattle = (id) => {
carterData.battleCounts[id] = (carterData.battleCounts[id] || 0) + 1;
return carterData.battleCounts[id];
};
// Optional: Add getter methods
window.carterData.getBattleCount = (id) => carterData.battleCounts[id] || 0;
window.carterData.getAllBattleCounts = () => ({ ...carterData.battleCounts });
// Function to stop the battle loop
window.stopBattles = () => {
console.log("Stopping battle loop...");
window.running = false;
};
// Function to set the battle ID dynamically
window.setBattleId = (newBattleId) => {
console.log(`Setting battle ID to ${newBattleId}`);
window.battleId = newBattleId;
};
function randomElementsInRange(arr, minNum, maxNum) {
// Validate input
if (minNum < 0 || maxNum > arr.length || minNum > maxNum) {
throw new Error("Invalid min or max for the given array");
}
// Pick a random number n between minNum and maxNum (inclusive)
const n = Math.floor(Math.random() * (maxNum - minNum + 1)) + minNum;
// Make a copy so we don't modify the original array
const arrCopy = [...arr];
// Fisher-Yates (Knuth) shuffle
for (let i = arrCopy.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[arrCopy[i], arrCopy[j]] = [arrCopy[j], arrCopy[i]];
}
// Return the first n elements from the shuffled array
return arrCopy.slice(0, n);
}
players = (await topPlayers())["userRecords"];
carters = players.filter((c)=>c["username"]=="carter")
const randCarter = ()=>setBattleId(randomElementsInRange(carters, 1,1)[0]["uuid"]);
function getUsernameCounts() {
if (!window.players || !Array.isArray(window.players)) {
console.error('Players data not found or invalid format');
return [];
}
// Count occurrences
const countMap = window.players.reduce((acc, player) => {
const username = player.username || 'anonymous';
acc[username] = (acc[username] || 0) + 1;
return acc;
}, {});
// Convert to sorted array
return Object.entries(countMap)
.sort((a, b) => b[1] - a[1] || a[0].localeCompare(b[0]))
.map(([username, count]) => ({ username, count }));
}
// Add to window object for access
window.getUsernameCounts = getUsernameCounts;
function getCarterEloLeaderboard() {
if (!window.players || !Array.isArray(window.players)) {
console.error('Players data not found');
return [];
}
return window.players
.filter(player =>
player.username === "carter" &&
player.word?.endsWith('" and this player wins.') &&
typeof player.elo === 'number'
)
.map(player => ({
emoji: player.word?.charAt(0) || '❌',
elo: player.elo,
uuid: player.uuid,
word: player.word
}))
.sort((a, b) => {
// Primary sort: ELO descending
if (b.elo !== a.elo) return b.elo - a.elo;
// Secondary sort: UUID ascending for ties
return a.uuid.localeCompare(b.uuid);
});
}
// Add to window object
window.getCarterEloLeaderboard = getCarterEloLeaderboard;
randCarter();
startBattles();
t = setInterval(randCarter,20000);
// Add to your existing code
let updateInterval;
async function updateStats() {
await stats();
}
function renderLeaderboard() {
const leaderboardData = window.getCarterEloLeaderboard();
const container = document.getElementById('carter-leaderboard') || createLeaderboardContainer();
// Clear existing content
container.innerHTML = '';
// Create title
const title = document.createElement('h2');
title.textContent = `Carter's Emoji Leaderboard (Updated: ${new Date().toLocaleTimeString()})`;
container.appendChild(title);
// Create list
const list = document.createElement('ul');
list.style.listStyleType = 'none';
list.style.padding = '0';
leaderboardData.forEach(player => {
const li = document.createElement('li');
li.style.margin = '10px 0';
li.style.padding = '10px';
li.style.backgroundColor = '#f5f5f5';
li.style.borderRadius = '5px';
li.innerHTML = `
<span style="font-size: 1.5em">${player.emoji}</span>
<span style="margin-left: 10px; font-weight: bold">ELO: ${player.elo.toFixed(2)}</span>
<div style="color: #666; margin-top: 5px">${player.word}</div>
`;
list.appendChild(li);
});
if (leaderboardData.length === 0) {
const empty = document.createElement('div');
empty.textContent = 'No carter players found';
list.appendChild(empty);
}
container.appendChild(list);
}
function createLeaderboardContainer() {
const existing = document.getElementById('carter-leaderboard');
if (existing) return existing;
const container = document.createElement('div');
container.id = 'carter-leaderboard';
container.style.position = 'fixed';
container.style.top = '20px';
container.style.right = '20px';
container.style.background = 'white';
container.style.padding = '20px';
container.style.borderRadius = '10px';
container.style.boxShadow = '0 2px 10px rgba(0,0,0,0.1)';
container.style.maxWidth = '400px';
container.style.zIndex = '1000';
document.body.appendChild(container);
return container;
}
async function renderAutoUpdatingLeaderboard() {
// Initial setup
await updateStats();
renderLeaderboard();
// Set up periodic updates
updateInterval = setInterval(async () => {
await updateStats();
renderLeaderboard();
}, 10000);
}
// Add controls to window
window.startLeaderboard = renderAutoUpdatingLeaderboard;
window.stopLeaderboard = () => {
clearInterval(updateInterval);
console.log("Leaderboard updates stopped");
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment