/
axe
/
gala
Обзор
Документация
Войти
/
axe
/
gala
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
modules/rubyBuilder.js
181 строка
6 KB
gusen
refactor 1
26 июн 2026, 17:15
26 июн 2026, 17:15
c828b36
Код
Авторство
О чём код?
import { formatNumber } from './common/utils.js'; import { saveBuilderCounts, loadBuilderCounts } from './common/storage.js'; import { calculateCoresNeeded } from './common/cores.js'; import { ICONS, votesToCounts } from './common/icons.js'; // Состояние let currentCounts = {}; let visualElement = null; let totalElement = null; function getDefaultCounts() { const defaults = {}; ICONS.forEach(icon => { defaults[icon.id] = 0; }); return defaults; } // Прямая конвертация (5 → 1, 3 → 1 для МЗЗ) function normalizeCounts() { let changed = true; while (changed) { changed = false; for (let i = 0; i < ICONS.length; i++) { const icon = ICONS[i]; if (currentCounts[icon.id] >= icon.maxStack) { const overflow = Math.floor(currentCounts[icon.id] / icon.maxStack); if (overflow > 0) { currentCounts[icon.id] -= overflow * icon.maxStack; const nextIcon = ICONS[i + 1]; if (nextIcon) { currentCounts[nextIcon.id] += overflow; changed = true; } else { currentCounts[icon.id] += overflow * icon.maxStack; } } } } } } function calculateTotalVotes() { let total = 0; ICONS.forEach(icon => { total += (currentCounts[icon.id] || 0) * icon.votes; }); return total; } function updateVisualDisplay() { if (!visualElement) return; visualElement.innerHTML = ''; let hasItems = false; for (let i = ICONS.length - 1; i >= 0; i--) { const icon = ICONS[i]; const count = currentCounts[icon.id] || 0; if (count > 0) { hasItems = true; for (let j = 0; j < count; j++) { const img = document.createElement('img'); img.src = icon.img; img.alt = icon.name; img.title = icon.name; img.style.cssText = 'width:36px;height:36px;object-fit:contain;margin:2px;'; visualElement.appendChild(img); } } } visualElement.innerHTML = hasItems ? visualElement.innerHTML : '<span style="color: #7f8c8d;">(ничего не выбрано)</span>'; if (totalElement) { totalElement.textContent = `${formatNumber(calculateTotalVotes())} голосов`; } } function handleBuilderClick(e) { const target = e.target; // Клик по иконке = +1 if (target.classList.contains('builder-img')) { const id = target.dataset.id; if (!id) return; currentCounts[id] = (currentCounts[id] || 0) + 1; normalizeCounts(); updateVisualDisplay(); saveBuilderCounts(currentCounts); return; } // Клик по кнопке - = -1 if (target.classList.contains('builder-minus')) { const id = target.dataset.id; if (!id) return; const icon = ICONS.find(i => i.id === id); if (!icon) return; const totalVotes = calculateTotalVotes(); if (totalVotes < icon.votes) return; const newVotes = totalVotes - icon.votes; currentCounts = votesToCounts(newVotes); updateVisualDisplay(); saveBuilderCounts(currentCounts); return; } } function renderBuilder(containerId) { const container = document.getElementById(containerId); if (!container) return; container.innerHTML = ''; const fragment = document.createDocumentFragment(); ICONS.forEach(icon => { const div = document.createElement('div'); div.className = 'builder-item'; div.innerHTML = ` <div class="builder-icon-wrapper"> <img class="builder-img" src="${icon.img}" alt="${icon.name}" data-id="${icon.id}" /> <button class="builder-minus" data-id="${icon.id}">−</button> </div> `; fragment.appendChild(div); }); container.appendChild(fragment); container.addEventListener('click', handleBuilderClick); } function setupCalculateButton() { const calcBtn = document.getElementById('calcFromBuilder'); if (!calcBtn) return; const newCalcBtn = calcBtn.cloneNode(true); calcBtn.parentNode.replaceChild(newCalcBtn, calcBtn); newCalcBtn.onclick = () => { const targetVotes = calculateTotalVotes(); const resultEl = document.getElementById('rubyResult'); if (targetVotes === 0) { resultEl.innerHTML = 'Сначала собери цель (нажми +)'; return; } const cores = calculateCoresNeeded(targetVotes); resultEl.innerHTML = ` Для достижения цели (${formatNumber(targetVotes)} голосов)<br> нужно набрать <strong>${formatNumber(targetVotes)}</strong> голосов.<br><br> <img src="./assets/images/cb/gball.png" class="core-icon"> Золотых ядер: ≈ ${cores.gold}<br> <img src="./assets/images/cb/fball.png" class="core-icon"> Огненных ядер: ≈ ${cores.fire}<br> <img src="./assets/images/cb/xball.png" class="core-icon"> Разрывных ядер: ≈ ${cores.explosive} `; }; } export function initRubyBuilder(containerId, visualId, totalId) { visualElement = document.getElementById(visualId); totalElement = document.getElementById(totalId); const saved = loadBuilderCounts(getDefaultCounts()); currentCounts = saved; normalizeCounts(); renderBuilder(containerId); updateVisualDisplay(); setupCalculateButton(); } export function resetBuilder() { currentCounts = getDefaultCounts(); normalizeCounts(); updateVisualDisplay(); saveBuilderCounts(currentCounts); }