(modelsData)
| 9491 | // Add these constants at the top with other constants |
| 9492 | const ROULETTE_SPINS = 10; // Number of models to highlight before stopping |
| 9493 | const ROULETTE_INITIAL_DELAY = 100; // Initial delay between highlights in ms |
| 9494 | const ROULETTE_DELAY_INCREMENT = 20; // How much to slow down each spin |
| 9495 | |
| 9496 | // Add the roulette functionality |
| 9497 | async function startPrintRoulette() { |
| 9498 | // Get all visible models in the grid |
| 9499 | const visibleModels = Array.from(document.querySelectorAll('.file-item')); |
| 9500 | if (visibleModels.length === 0) return; |
| 9501 | |
| 9502 | // Clear any existing selections |
| 9503 | selectedModels.clear(); |
| 9504 | document.querySelectorAll('.file-item').forEach(item => { |
| 9505 | item.classList.remove('selected'); |
| 9506 | }); |
| 9507 | |
| 9508 | // Close details panel if open |
| 9509 | const detailsPanel = document.getElementById('model-details'); |
| 9510 | if (detailsPanel) { |
| 9511 | detailsPanel.classList.add('hidden'); |
| 9512 | } |
| 9513 | |
| 9514 | let delay = ROULETTE_INITIAL_DELAY; |
| 9515 | let previousItem = null; |
| 9516 | |
| 9517 | // Function to highlight a random item. |
| 9518 | // Pass doScroll=true to scroll the item into view. |
| 9519 | const highlightRandom = (doScroll = false) => { |
| 9520 | if (previousItem) { |
| 9521 | previousItem.classList.remove('selected'); |
| 9522 | } |
| 9523 | const randomIndex = Math.floor(Math.random() * visibleModels.length); |
| 9524 | const randomItem = visibleModels[randomIndex]; |
| 9525 | randomItem.classList.add('selected'); |
| 9526 | if (doScroll) { |
| 9527 | randomItem.scrollIntoView({ behavior: 'smooth', block: 'center' }); |
| 9528 | } |
| 9529 | previousItem = randomItem; |
| 9530 | return randomItem; |
| 9531 | }; |
| 9532 | |
| 9533 | // Spin animation without scrolling (to avoid white flashes) |
| 9534 | for (let i = 0; i < ROULETTE_SPINS; i++) { |
| 9535 | await new Promise(resolve => setTimeout(resolve, delay)); |
| 9536 | highlightRandom(); // no scrolling on intermediate spins |
| 9537 | delay += ROULETTE_DELAY_INCREMENT; // Gradually slow down |
| 9538 | } |
| 9539 | |
| 9540 | // Final selection with scrolling. |
| 9541 | const finalItem = highlightRandom(true); |
| 9542 | const filePath = finalItem.getAttribute('data-filepath'); |
| 9543 | |
| 9544 | // Add winning animation class |
| 9545 | finalItem.classList.add('roulette-winner'); |
| 9546 | setTimeout(() => finalItem.classList.remove('roulette-winner'), 3000); |
| 9547 | |
| 9548 | // Show model details and update selection state |
| 9549 | selectedModels.add(filePath); |
| 9550 | await showModelDetails(filePath); |
no test coverage detected