Download script.js from ProjectGenesis/loot-spin-bonanza: direct link, hf CLI and curl.
- Browser
- Download file 5.15 kB
-
https://huggingface.co/spaces/ProjectGenesis/loot-spin-bonanza/resolve/main/script.js
- Command line
-
hf download hf://spaces/ProjectGenesis/loot-spin-bonanza/script.js
-
curl -L -o script.js https://huggingface.co/spaces/ProjectGenesis/loot-spin-bonanza/resolve/main/script.js
5.15 kB
| document.addEventListener('DOMContentLoaded', () => { | |
| // DOM Elements | |
| const lootTrack = document.getElementById('lootTrack'); | |
| const lootWrapper = document.getElementById('lootWrapper'); | |
| const multiTrack = document.getElementById('multiTrack'); | |
| const multiWrapper = document.getElementById('multiWrapper'); | |
| const spinBtn = document.getElementById('spinBtn'); | |
| const popupBackdrop = document.getElementById('popupBackdrop'); | |
| const popupTotal = document.getElementById('popupTotal'); | |
| const popupBase = document.getElementById('popupBase'); | |
| const popupMulti = document.getElementById('popupMulti'); | |
| const popupClose = document.getElementById('popupClose'); | |
| // Loot Box Data | |
| const lootBoxesData = [ | |
| { prize: 10, rarity: 'green' }, | |
| { prize: 15, rarity: 'blue' }, | |
| { prize: 20, rarity: 'blue' }, | |
| { prize: 25, rarity: 'green' }, | |
| { prize: 30, rarity: 'purple' }, | |
| { prize: 35, rarity: 'purple' }, | |
| { prize: 40, rarity: 'green' }, | |
| { prize: 45, rarity: 'blue' }, | |
| { prize: 50, rarity: 'purple' }, | |
| { prize: 100, rarity: 'gold' } | |
| ]; | |
| // Multiplier Data | |
| const multipliers = [1, 1.25, 1.5, 2, 3, 5, 1, 1.25, 1.5, 2, 3, 5]; | |
| // Initialize tracks | |
| function initializeTracks() { | |
| // Create loot boxes | |
| lootBoxesData.forEach(box => { | |
| const boxElement = document.createElement('div'); | |
| boxElement.className = 'loot-box'; | |
| boxElement.dataset.prize = box.prize; | |
| boxElement.dataset.rarity = box.rarity; | |
| const inner = document.createElement('div'); | |
| inner.className = 'loot-box-inner'; | |
| boxElement.appendChild(inner); | |
| lootTrack.appendChild(boxElement); | |
| }); | |
| // Create multiplier pills | |
| multipliers.forEach(m => { | |
| const pill = document.createElement('div'); | |
| pill.className = 'multi-pill'; | |
| pill.dataset.m = m; | |
| pill.textContent = `×${m}`; | |
| multiTrack.appendChild(pill); | |
| }); | |
| } | |
| // Spin animation function | |
| async function spinTrack(track, items, wrapper, extraMinSteps, extraMaxSteps, duration) { | |
| return new Promise(resolve => { | |
| // Reset classes | |
| items.forEach(el => { | |
| el.classList.remove('selected', 'motion-blur'); | |
| }); | |
| const targetIndex = Math.floor(Math.random() * items.length); | |
| const wrapperRect = wrapper.getBoundingClientRect(); | |
| const centerX = wrapperRect.left + wrapperRect.width / 2; | |
| const targetRect = items[targetIndex].getBoundingClientRect(); | |
| const targetCenter = targetRect.left + targetRect.width / 2; | |
| const deltaToCenter = centerX - targetCenter; | |
| // Calculate step size | |
| let step = 0; | |
| if (items.length > 1) { | |
| const r0 = items[0].getBoundingClientRect(); | |
| const r1 = items[1].getBoundingClientRect(); | |
| step = Math.abs((r1.left + r1.width / 2) - (r0.left + r0.width / 2)); | |
| } else { | |
| step = targetRect.width + 18; | |
| } | |
| const extraSteps = extraMinSteps + Math.floor(Math.random() * (extraMaxSteps - extraMinSteps + 1)); | |
| const direction = Math.random() > 0.5 ? 1 : -1; | |
| const extraDistance = extraSteps * step * direction; | |
| const currentTranslate = parseFloat(track.style.transform?.replace('translateX(', '').replace('px)', '') || '0'); | |
| const finalTranslate = currentTranslate + deltaToCenter + extraDistance; | |
| // Apply motion blur | |
| items.forEach((el, i) => { | |
| if (i !== targetIndex) el.classList.add('motion-blur'); | |
| }); | |
| // Start animation | |
| track.style.transition = `transform ${duration}ms cubic-bezier(0.1, 0.9, 0.24, 1)`; | |
| track.style.transform = `translateX(${finalTranslate}px)`; | |
| setTimeout(() => { | |
| track.style.transition = ''; | |
| items.forEach(el => el.classList.remove('motion-blur')); | |
| items[targetIndex].classList.add('selected'); | |
| resolve({ index: targetIndex, element: items[targetIndex] }); | |
| }, duration + 40); | |
| }); | |
| } | |
| // Handle spin button click | |
| async function handleSpin() { | |
| if (spinBtn.disabled) return; | |
| spinBtn.disabled = true; | |
| // Spin loot boxes | |
| const lootResult = await spinTrack(lootTrack, [...lootTrack.children], lootWrapper, 3, 6, 1100); | |
| const basePrize = parseFloat(lootResult.element.dataset.prize); | |
| // Spin multiplier | |
| const multiResult = await spinTrack(multiTrack, [...multiTrack.children], multiWrapper, 4, 7, 1000); | |
| const multiplier = parseFloat(multiResult.element.dataset.m); | |
| // Calculate total | |
| const total = Math.round(basePrize * multiplier * 100) / 100; | |
| // Show result | |
| popupTotal.textContent = `${total} SC`; | |
| popupBase.textContent = `Base: ${basePrize} SC`; | |
| popupMulti.textContent = `Multiplier: ×${multiplier}`; | |
| popupBackdrop.classList.remove('hidden'); | |
| spinBtn.disabled = false; | |
| } | |
| // Event listeners | |
| spinBtn.addEventListener('click', handleSpin); | |
| popupClose.addEventListener('click', () => { | |
| popupBackdrop.classList.add('hidden'); | |
| }); | |
| popupBackdrop.addEventListener('click', (e) => { | |
| if (e.target === popupBackdrop) { | |
| popupBackdrop.classList.add('hidden'); | |
| } | |
| }); | |
| // Initialize | |
| initializeTracks(); | |
| }); |