Last active
June 5, 2025 14:56
-
-
Save josephfusco/9b6547cf1138e7db7bdfcf01b70f2253 to your computer and use it in GitHub Desktop.
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
// Word lists | |
const nounsOpenSource = [ | |
'Fork', 'Commit', 'Patch', 'Module', 'Branch', 'Merge', 'Token', 'Kernel', 'Repo', 'Hook' | |
]; | |
const nounsWordPress = [ | |
'Plugin', 'Theme', 'Block', 'Template', 'Dashboard', 'Widget', 'Post', 'Page', 'Core', 'Loop' | |
]; | |
const nounsHeadless = [ | |
'GraphQL', 'API', 'Endpoint', 'Resolver', 'Payload', 'Schema', 'Client', 'Cache', 'TokenAuth', 'Webhook' | |
]; | |
const adjectivesPopCulture = [ | |
'Matrix', 'Mandalorian', 'Skywalker', 'Stark', 'Gandalf', 'Spock', 'Kenobi', | |
'X-Men', 'Hobbit', 'Neo', 'Vulcan', 'Lannister', 'Sith', 'Potter' | |
]; | |
const nounsDnDGame = [ | |
'Dungeon', 'Quest', 'Boss', 'Mana', 'Crit', 'XP', 'Potion', 'Loot', 'Spell', 'Dragon', | |
'Blade', 'Warlock', 'Rogue', 'Knight', 'Tavern' | |
]; | |
const modifiersFantasy = ['Ancient', 'Cursed', 'Lost', 'Arcane', 'Forgotten', 'Infernal']; | |
const templates = [ | |
'{adj} and the {game} of the {wp}', | |
'The {game} of {adj}\'s {wp}', | |
'{open} in the {game} of {adj}', | |
'Chronicles of {adj}: The {mod} {game}', | |
'{mod} {wp} of the {headless} {game}', | |
'The {mod} {game} of {adj} the {open}' | |
]; | |
const emojiMap = { | |
'Warlock': 'π§ββοΈ', | |
'Spell': 'πͺ', | |
'Blade': 'π‘οΈ', | |
'Rogue': 'π‘οΈ', | |
'Knight': 'π‘οΈ', | |
'Boss': 'π', | |
'Dragon': 'π²', | |
'Dungeon': 'π°', | |
'Tavern': 'πΊ', | |
'Mana': 'π«', | |
'XP': 'π', | |
'Potion': 'π§ͺ', | |
'Loot': 'π°' | |
}; | |
function pickRandom(arr, seen = new Set()) { | |
const options = arr.filter(item => !seen.has(item)); | |
const choice = options.length > 0 ? options[Math.floor(Math.random() * options.length)] : arr[Math.floor(Math.random() * arr.length)]; | |
seen.add(choice); | |
return choice; | |
} | |
function titleCase(str) { | |
return str.replace(/\w\S*/g, w => w.charAt(0).toUpperCase() + w.slice(1).toLowerCase()); | |
} | |
function generateSprintName(usedWords) { | |
const template = pickRandom(templates); | |
const adj = titleCase(pickRandom(adjectivesPopCulture, usedWords)); | |
const open = titleCase(pickRandom(nounsOpenSource, usedWords)); | |
const wp = titleCase(pickRandom(nounsWordPress, usedWords)); | |
const headless = titleCase(pickRandom(nounsHeadless, usedWords)); | |
const game = titleCase(pickRandom(nounsDnDGame, usedWords)); | |
const mod = titleCase(pickRandom(modifiersFantasy, usedWords)); | |
const raw = template.replace(/\{(\w+)\}/g, (_, key) => ({ adj, open, wp, headless, game, mod }[key])); | |
const emoji = emojiMap[game] || ''; | |
return `${emoji} ${raw}`.trim(); | |
} | |
function generateSprintBoard(count = 10) { | |
const seen = new Set(); | |
const board = []; | |
while (board.length < count) { | |
const name = generateSprintName(seen); | |
if (!board.includes(name)) { | |
board.push(name); | |
} | |
} | |
return board; | |
} | |
// Run it | |
generateSprintBoard(5).forEach((name, i) => console.log(`${i + 1}. ${name}`)); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment