/* HTML generation */ const TYPES = { Grass: '🍃', Fire: '🔥', Water: '💧', Lightning: '⚡', Fighting: '✊', Psychic: '👁️', Colorless: '⭐', Darkness: '🌑', Metal: '⚙️', Dragon: '🐲', Fairy: '🧚', }; const energyHTML = (type, types = TYPES) => { return `${types[type]}`; }; const attackDescriptionHTML = (text) => { if (!text) { return ''; } let fontSize; if (text.length > 185) { fontSize = 0.7; } else if (text.length > 140) { fontSize = 0.8; } else if (text.length > 90) { fontSize = 0.9; } return `${text}`; }; const attackRowsHTML = (attacks) => { return attacks .map((attack) => { const { cost, damage, name, text } = attack; return `
  • ${cost.map((energy) => energyHTML(energy)).join('')}
    ${name} ${attackDescriptionHTML(text)} ${damage ? damage : ''}

  • `; }) .join(''); }; const cardHTML = (details) => { const { hp, energy_type, species, length, weight, attacks, weakness, resistance, retreat, description, rarity } = details; const poke_name = details.name; // `name` would be reserved JS word return `

    Basic Pokémon

    ${poke_name}

    ${hp} HP ${energyHTML(energy_type)}
    AI generated Pokémon called ${poke_name}
    ${species} Pokémon. Length: ${length.feet}'${length.inches}", Weight: ${weight}
    weakness ${weakness ? energyHTML(weakness) : ''}
    resistance ${resistance ? energyHTML(resistance) : ''} ${resistance ? '-30' : ''}
    retreat cost
    ${energyHTML('Colorless').repeat(retreat)}

    ${description}

    `; }; /* Utility */ const getBasePath = () => { return document.location.origin + document.location.pathname; }; const generateDetails = async () => { const details = await fetch(`${getBasePath()}/details`); return await details.json(); }; const createTask = async (prompt) => { const taskResponse = await fetch(`${getBasePath()}task/create?prompt=${prompt}`); const task = await taskResponse.json(); return task; }; const queueTask = (task_id) => { fetch(`${getBasePath()}task/queue?task_id=${task_id}`); }; const pollTask = async (task) => { const taskResponse = await fetch(`${getBasePath()}task/poll?task_id=${task.task_id}`); return await taskResponse.json(); }; const longPollTask = async (task, interval = 5_000, max) => { if (task.status === 'complete' || (max && task.poll_count > max)) { return task; } const taskResponse = await fetch(`${getBasePath()}task/poll?task_id=${task.task_id}`); task = await taskResponse.json(); if (task.status === 'complete' || task.poll_count > max) { return task; } await new Promise((resolve) => setTimeout(resolve, interval)); return await longPollTask(task, interval, max); }; /* DOM */ const generateButton = document.querySelector('button.generate'); const rotateCard = () => { const RANGE = 0.1; const INTERVAL = 13; // ~75 per second let previousTime = 0; // Throttle closure return (card, containerMouseEvent) => { const currentTime = performance.now(); if (currentTime - previousTime > INTERVAL) { previousTime = currentTime; const rect = card.getBoundingClientRect(); const rotateX = (containerMouseEvent.clientY - rect.y - rect.height / 2) * RANGE; const rotateY = -(containerMouseEvent.clientX - rect.x - rect.width / 2) * RANGE; card.style.setProperty('--rotate-x', rotateX + 'deg'); card.style.setProperty('--rotate-y', rotateY + 'deg'); } }; }; const cardRotationInitiator = (renderSection) => { let currentCard; return () => { let handleMouseMove; if (currentCard) { handleMouseMove = rotateCard().bind(null, currentCard); renderSection.removeEventListener('mousemove', handleMouseMove, true); } const newCard = document.querySelector('.pokecard'); currentCard = newCard; handleMouseMove = rotateCard().bind(null, newCard); renderSection.addEventListener('mousemove', handleMouseMove, true); }; }; generateButton.addEventListener('click', async () => { const details = await generateDetails(); console.log({ details }); const renderSection = document.querySelector('section.render'); const durationSeconds = document.querySelector('.duration > .seconds'); const initialiseCardRotation = cardRotationInitiator(renderSection); let duration = 0.0; try { const task = await createTask(details.energy_type); queueTask(task.task_id); const incrementSeconds = setInterval(() => { duration += 0.1; durationSeconds.textContent = duration.toFixed(1).toString(); }, 100); const completedTask = await longPollTask(task); clearInterval(incrementSeconds); renderSection.innerHTML = cardHTML(details); const picture = document.querySelector('img.picture'); picture.src = completedTask.value; initialiseCardRotation(); } catch (err) { console.error(err); } });