let testwagerAction = 0; let testwager = 0; let testMoneyLost = 0; let testMoneyWon = 0; let ThirdActionBoolean = 0; let ThirdActionBooleancoef = 785; let RefferedCommissionToGifter = 0; let ReferalGiftUse = 0; let gamesPlayed2 = 0; const fixedRates = { BTC: 97020, ETH: 2665, USDT: 1, LTC: 110, BNB: 615, MATIC: 1.2, SOL: 205, TON: 0.4, USDC: 1, XRP: 2.5, }; // Во внешнем скрипте (async function () { await loadUserDataFromDatabase(); // дождемся выполнения await updateUILogoAffiliated(); // затем вызовем updateUILogo await updateUILogoGames(); await updateCoinName(); let Tempg = await getUserValue(telegramUserId, 'moneyWon'); Tempg = parseFloat(Tempg) || 0; testMoneyWon += Tempg; Tempg = await getUserValue(telegramUserId, 'moneyLost'); Tempg = parseFloat(Tempg) || 0; testMoneyLost += Tempg; Tempg = await getUserValue(telegramUserId, 'wagered'); Tempg = parseFloat(Tempg) || 0; testwager += Tempg; Tempg = await getUserValue(telegramUserId, 'gamesPlayed'); Tempg = parseFloat(Tempg) || 0; gamesPlayed2 += Tempg; Tempg = await getUserValue(telegramUserId, 'SecondActionWagered'); Tempg = parseFloat(Tempg) || 0; testwagerAction += Tempg; Tempg = await getUserValue(telegramUserId, 'RefferedCommissionToGifter'); Tempg = parseFloat(Tempg) || 0; RefferedCommissionToGifter += Tempg; Tempg = await getUserValue(telegramUserId, 'ReferalGiftUse'); if (Tempg) { ReferalGiftUse = true; } else { ReferalGiftUse = false; } myBets = await getUserValue(telegramUserId, 'MyBets'); iconPathTable = await getUserValue(telegramUserId, 'iconPath'); })(); async function updateSelectedBalance() { const selectedColumn = await getUserValue( telegramUserId, "selectedBalanceId" ); // ожидаем результат if (selectedColumn) { await updateUser(telegramUserId, selectedColumn, balance); // обновляем баланс document.getElementById(selectedColumn).textContent = balance.toFixed(8); } else { console.error("Не удалось получить выбранный баланс пользователя."); } } async function updateBiggestCoefIfHigher(telegramUserId, WinCoef) { try { // Получаем текущее значение biggestCoef const currentBiggestCoef = await getUserValue( telegramUserId, "biggestCoef" ); // Проверяем, если WinCoef больше текущего значения biggestCoef if (parseFloat(currentBiggestCoef) < WinCoef) { // Обновляем biggestCoef, если WinCoef больше await updateUser(telegramUserId, "biggestCoef", WinCoef); } } catch (error) { } } async function updateBiggestWinIfHigher(telegramUserId, WinAmountGlobal) { try { const currentbiggestwin = await getUserValue(telegramUserId, "biggestwin"); if (parseFloat(currentbiggestwin) < WinAmountGlobal) { await updateUser(telegramUserId, "biggestwin", WinAmountGlobal); } } catch (error) { } } async function UpdateLastBiggestBet(telegramUserId, Amount) { try { const currentLastbiggestBet = await getUserValue( telegramUserId, "LastBiggestBet" ); if (Math.abs(Amount) >= Math.abs(currentLastbiggestBet)) { await updateUser(telegramUserId, "LastBiggestBet", Amount); await updateUser(telegramUserId, "LastBiggestBetGame", "Dragon Tower"); updateLastInteraction(telegramUserId); } } catch (error) { } } async function saveGameData() { updateBiggestCoefIfHigher(telegramUserId, WinCoef); updateBiggestWinIfHigher(telegramUserId, winAmountGlobal); const selectedColumn = await getUserValue(telegramUserId, 'selectedBalanceId'); // ожидаем результат if (selectedColumn) { await updateUser(telegramUserId, selectedColumn, balance); // обновляем баланс document.getElementById(selectedColumn).textContent = balance.toFixed(8); } else { console.error('Не удалось получить выбранный баланс пользователя.'); } updateUser(telegramUserId, 'balance', balance); updateUser(telegramUserId, 'gamesPlayed', gamesPlayed2); updateUser(telegramUserId, 'moneyWon', testMoneyWon); updateUser(telegramUserId, 'moneyLost', testMoneyLost); updateUser(telegramUserId, 'gamesWon', gamesWon); updateUser(telegramUserId, 'gamesLost', gamesLost); updateUser(telegramUserId, 'wagered', testwager.toFixed(2)); updateUser(telegramUserId, 'RacingDailyAction', testwager); async function processWagerAction() { while (testwagerAction.toFixed(2) >= 200) { testwagerAction -= 200; await addUniqueTicketNumber(); // Ждем завершения каждого запроса } updateUser(telegramUserId, 'SecondActionWagered', testwagerAction.toFixed(2)); } processWagerAction(); updateUser(telegramUserId, 'SecondActionWagered', testwagerAction.toFixed(2)); } const betAmountInput = document.getElementById("bet"); const halveButton = document.getElementById("halve"); const doubleButton = document.getElementById("double"); // Функция для получения и преобразования значения из input function getBetAmount() { // Преобразуем строку из input в число, если это не валидное число — возвращаем 0 let amount = parseFloat(betAmountInput.value); return isNaN(amount) ? 0 : amount; } // Функция для установки значения в input с двумя знаками после запятой function setBetAmount(value) { if (parseFloat(betAmountInput.value) === 0 || !betAmountInput.value) { value = 0.00000001; } betAmountInput.value = value.toFixed(8); } // Обработчик для кнопки «½» halveButton.addEventListener("click", () => { let currentAmount = getBetAmount(); setBetAmount(currentAmount / 2); }); // Обработчик для кнопки «2×» doubleButton.addEventListener("click", () => { let currentAmount = getBetAmount(); setBetAmount(currentAmount * 2); }); // document.getElementById('Reset').addEventListener('click', function () { // // Add 'active' class to Reset, remove from IncreaseBy // this.classList.add('active'); // document.getElementById('IncreaseBy').classList.remove('active'); // // Disable input and remove 'active' class from input field // document.getElementById('win-increase').disabled = true; // document.getElementById('win-increase').value = 0; // document.getElementById('win-increase').classList.remove('active'); // document.getElementById('win-increase2').disabled = true; // document.getElementById('win-increase2').classList.remove('active'); // }); // document.getElementById('IncreaseBy').addEventListener('click', function () { // // Add 'active' class to IncreaseBy, remove from Reset // this.classList.add('active'); // document.getElementById('Reset').classList.remove('active'); // // Enable input and add 'active' class to input field // document.getElementById('win-increase').disabled = false; // document.getElementById('win-increase').classList.add('active'); // document.getElementById('win-increase2').disabled = false; // document.getElementById('win-increase2').classList.add('active'); // }); // document.getElementById('Reset2').addEventListener('click', function () { // // Add 'active' class to Reset, remove from IncreaseBy // this.classList.add('active'); // document.getElementById('IncreaseBy2').classList.remove('active'); // // Disable input and remove 'active' class from input field // document.getElementById('loss-increase').disabled = true; // document.getElementById('loss-increase').value = 0; // document.getElementById('loss-increase').classList.remove('active'); // document.getElementById('loss-increase2').disabled = true; // document.getElementById('loss-increase2').classList.remove('active'); // }); // document.getElementById('IncreaseBy2').addEventListener('click', function () { // // Add 'active' class to IncreaseBy, remove from Reset // this.classList.add('active'); // document.getElementById('Reset2').classList.remove('active'); // // Enable input and add 'active' class to input field // document.getElementById('loss-increase').disabled = false; // document.getElementById('loss-increase').classList.add('active'); // document.getElementById('loss-increase2').disabled = false; // document.getElementById('loss-increase2').classList.add('active'); // }); function showTab(tabId) { const tabs = document.querySelectorAll(".table"); const buttons = document.querySelectorAll(".mode-btn2"); tabs.forEach((tab) => { tab.classList.remove("active"); }); buttons.forEach((button) => { button.classList.remove("active"); }); document.getElementById(tabId).classList.add("active"); document .querySelector(`[onclick="showTab('${tabId}')"]`) .classList.add("active"); } const autoGamesInput = document.getElementById("auto-games"); const infinitySymbol = document.querySelector(".infinity-symbol"); // // Function to show or hide the infinity symbol // function toggleInfinitySymbol() { // if (autoGamesInput.value === '' || autoGamesInput.value === '0') { // infinitySymbol.classList.remove('hidden'); // } else { // infinitySymbol.classList.add('hidden'); // } // } // Add an event listener to update on input changes // autoGamesInput.addEventListener('input', toggleInfinitySymbol); // Initial check when the page loads // toggleInfinitySymbol(); async function addUniqueTicketNumber() { try { const response = await fetch("http://localhost:3000/add-unique-ticket", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ telegram_user_id: telegramUserId }), }); const data = await response.json(); if (data.error) { console.error(`Ошибка: ${data.error}`); } else { console.log(`Уникальный номер билета добавлен: ${data.ticketNumber}`); } } catch (error) { console.error("Ошибка при добавлении уникального номера билета:", error); } } let coinName = null; async function updateCoinName() { try { let iconPath = await getUserValue(telegramUserId, "iconPath"); coinName = iconPath.split("/").pop().split(".").shift(); // Берем последнее слово после "/"" и убираем расширение } catch (error) { } } async function fetchCryptoRates() { try { const response = await fetch('https://min-api.cryptocompare.com/data/pricemulti?fsyms=BTC,TON,ETH,USDT,LTC,SOL,USDC,XRP,BNB,POL&tsyms=USD'); const data = await response.json(); return { USDT: data.USDT?.USD || 0, ETH: data.ETH?.USD || 0, BTC: data.BTC?.USD || 0, TON: data.TON?.USD || 0, LTC: data.LTC?.USD || 0, SOL: data.SOL?.USD || 0, USDC: data.USDC?.USD || 0, XRP: data.XRP?.USD || 0, BNB: data.BNB?.USD || 0, POL: data.POL?.USD || 0 // Добавляем курс POL }; } catch (error) { console.error('Error fetching cryptocurrency rates:', error); return null; // В случае ошибки возвращаем null } } async function convertToUSDT(amount, currency) { const rates = await fetchCryptoRates(); if (!rates || !rates.USDT || !rates[currency]) { console.error("Rates not available or invalid currency"); return null; } // Находим курс USDT к USD и текущий курс указанной валюты к USD const usdtRate = rates.USDT; const currencyRate = rates[currency]; // Переводим сумму в USDT const amountInUSDT = (amount * currencyRate) / usdtRate; return amountInUSDT; } async function updateRefferedCommissionToGifter(bet) { const selectedColumn = await getUserValue( telegramUserId, "selectedBalanceId" ); const currency = selectedColumn.replace("balance", ""); // Удаляет слово "balance" if (ReferalGiftUse) { convertToUSDT(bet, currency).then((result) => { RefferedCommissionToGifter += parseFloat(result); updateUser( telegramUserId, "RefferedCommissionToGifter", RefferedCommissionToGifter ); }); } } async function UpdateWageredLostWon(bet, GameResult) { const selectedColumn = await getUserValue(telegramUserId, 'selectedBalanceId'); const currency = selectedColumn.replace('balance', ''); if (GameResult === "win") { convertToUSDT(bet, currency).then(result => { testMoneyWon += parseFloat(Number(result)); }); } else { convertToUSDT(bet, currency).then(result => { testMoneyLost += parseFloat(Number(result)); }); } } async function updateRefferedSUMMCommission(bet) { const selectedColumn = await getUserValue(telegramUserId, 'selectedBalanceId'); if (ReferalGiftUse) { try { // Получаем текущее значение RefferedSUMMCommission let currentCommission = await getUserValue(telegramUserId, 'RefferedSUMMCommission'); // Парсим JSON, если это строка if (typeof currentCommission === 'string') { try { currentCommission = JSON.parse(currentCommission); } catch (error) { console.error('Ошибка при парсинге JSON:', error); currentCommission = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; // Пустой массив на случай ошибки } } // Убедимся, что это массив if (!Array.isArray(currentCommission)) { currentCommission = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; } if (selectedColumn === "balanceUSDT") { currentCommission[0] += bet; } if (selectedColumn === "balanceETH") { currentCommission[1] += bet; } if (selectedColumn === "balanceBTC") { currentCommission[2] += bet; } if (selectedColumn === "balanceTON") { currentCommission[3] += bet; } if (selectedColumn === "balanceLTC") { currentCommission[4] += bet; } if (selectedColumn === "balanceSOL") { currentCommission[5] += bet; } if (selectedColumn === "balanceUSDC") { currentCommission[6] += bet; } if (selectedColumn === "balanceXRP") { currentCommission[7] += bet; } if (selectedColumn === "balanceBNB") { currentCommission[8] += bet; } if (selectedColumn === "balancePOL") { currentCommission[9] += bet; } // Сохраняем обновленный массив в базе данных await updateUser(telegramUserId, 'RefferedSUMMCommission', JSON.stringify(currentCommission)); console.log('RefferedSUMMCommission успешно обновлен:', currentCommission); } catch (error) { console.error('Ошибка при обновлении RefferedSUMMCommission:', error); } } } async function addBetToMyBets(betResult) { try { let myBets = await getUserValue(telegramUserId, "MyBets"); if (typeof myBets === "string") { try { myBets = JSON.parse(myBets); // Парсим строку JSON } catch (error) { console.error("Ошибка при парсинге JSON:", error); myBets = []; // Пустой массив в случае ошибки } } // Если myBets - не массив, инициализируем его пустым массивом if (!Array.isArray(myBets)) { console.warn("Неверный формат данных, инициализация пустым массивом"); myBets = []; } // Добавляем betResult в начало массива myBets myBets.unshift(betResult); if (myBets.length > 46) { myBets.pop(); } // Форматируем массив для отображения const formattedBets = myBets .map((bet) => `${bet.name}: ${bet.result}`) .join(", "); // Сохраняем обновленный массив, если это необходимо await updateUser(telegramUserId, "MyBets", JSON.stringify(myBets)); } catch (error) { } } const betInput = document.getElementById("bet"); const startButton = document.getElementById("start-btn"); const betInputbox = document.getElementById("betbox"); // Функция для проверки валидности ставки function checkBetValue(event) { const betValue = parseFloat(betInput.value); if (event && (isNaN(betValue) || betValue < 0.00000001)) { betInputbox.style.borderColor = "red"; startButton.disabled = true; } else if (event) { betInputbox.style.borderColor = ""; } } betInput.addEventListener("input", (event) => checkBetValue(event)); checkBetValue(); function disableInput(inputElement) { inputElement.setAttribute("disabled", "true"); inputElement.parentElement.style.backgroundColor = "#203341"; // Меняем фон } function enableInput(inputElement) { inputElement.removeAttribute("disabled"); inputElement.parentElement.style.backgroundColor = "#0f212f"; // Возвращаем исходный цвет } // document.getElementById('win-increase').addEventListener('input', () => { // winIncreasePercentage = parseInt(document.getElementById('win-increase').value); // }); // document.getElementById('loss-increase').addEventListener('input', () => { // lossIncreasePercentage = parseInt(document.getElementById('loss-increase').value); // }); //God save this code //GAME document.addEventListener("DOMContentLoaded", () => { const canvas = document.getElementById("crash-canvas"); const ctx = canvas.getContext("2d"); const dpr = window.devicePixelRatio || 1; const historyContainer = document.querySelector(".history-info-block"); const multiplierDisplay = document.createElement("div"); multiplierDisplay.style.fontFamily = "Outfit"; multiplierDisplay.style.fontSize = "30px"; multiplierDisplay.id = "multiplier"; multiplierDisplay.style.position = "absolute"; multiplierDisplay.style.transform = "translate(-50%, -50%)"; multiplierDisplay.style.zIndex = "10"; multiplierDisplay.innerText = "1.00x"; canvas.parentElement.appendChild(multiplierDisplay); function updateMultiplierPosition() { const canvasRect = canvas.getBoundingClientRect(); multiplierDisplay.style.top = `${canvas.offsetTop + canvas.clientHeight * 0.5 }px`; multiplierDisplay.style.left = `${canvas.offsetLeft + canvas.clientWidth / 1.9 }px`; } window.addEventListener("resize", updateMultiplierPosition); window.addEventListener("scroll", updateMultiplierPosition); updateMultiplierPosition(); canvas.style.width = `${canvas.offsetWidth}px`; canvas.style.height = `${canvas.offsetHeight}px`; canvas.width = canvas.offsetWidth * dpr; canvas.height = canvas.offsetHeight * dpr; ctx.scale(dpr, dpr); ctx.imageSmoothingEnabled = false; const historyData = []; oldCanvasWidth = 360; oldCanvasHeight = 245; //360 245 let isGameRunning = false; window.isRoundActive = false; window.isBetweenRounds = true; window.isBetPlaced = false; let isCrashed = false; let userCashoutMultiplier = null; let currentMultiplier = 1.0; let crashPoint = getRandomCrashPoint(); let startTime = null; let totalTime = 0; let userBet = 0; let lockedCashoutValue = null; // 📐 Отступы и размеры графика const MARGIN = 30; let GRAPH_WIDTH = 270; let GRAPH_HEIGHT = 185; // 270 185 let MAX_TIME = 10; let MAX_MULTIPLIER = 2.0; const OX_LABELS = 5; const OY_LABELS = 6; const OFFSET_X = 10; const cashoutInput = document.getElementById("cashout-input"); const cashoutIncrease = document.getElementById("cashout-increase"); const cashoutDecrease = document.getElementById("cashout-decrease"); let cashoutValue = parseFloat(cashoutInput.value) || 1.0; window.isAutoMode = false; // Флаг для отслеживания Auto режима window.autoPlaying = false; // Флаг работы автоигры const betsInput = document.getElementById("bets-input"); window.infinitySign = document.getElementById("infinity-sign"); startButton.addEventListener("click", () => { if (isAutoMode) { autoPlaying ? stopAutoBet() : startAutoBet(); } else { if (isBetweenRounds && !isBetPlaced) { placeBet(); } else if (isRoundActive) { cashOut(); } } }); window.placeBet = async function () { if (window.isAutoMode) { if (!window.autoPlaying || window.remainingBets <= 0) return; } userBet = parseFloat(betInput.value); lockedCashoutValue = cashoutValue; if (isNaN(userBet) || userBet < 0.00000001) { //alert("Please enter a valid bet amount."); return; } if (userBet > balance) { //alert("Not enough balance for a bet"); return; } isBetPlaced = true; window.updateStartButtonText(); startButton.disabled = true; document.getElementById("balance").textContent = ( parseFloat(balance) - parseFloat(userBet) ).toFixed(8); await updateCoinName(); const user = { name: telegramUserId, multiplier: "-", token: coinName, usdBet: 1, tokenBet: userBet, winAmount: 1, }; const userTable = document.getElementById("user-table"); const row = document.createElement("div"); row.classList.add("user-row"); const nameCell = document.createElement("div"); nameCell.classList.add("user-name"); nameCell.innerHTML = `${user.name}id`; const multiplierCell = document.createElement("div"); multiplierCell.classList.add("user-multiplier"); multiplierCell.textContent = user.multiplier; const winCell = document.createElement("div"); winCell.classList.add("user-win"); const img = document.createElement("img"); img.src = `../Images/${user.token}.png`; img.alt = user.token; img.style.width = "16px"; img.style.height = "16px"; img.style.marginRight = "5px"; winCell.appendChild(img); const text = document.createTextNode(user.tokenBet); winCell.appendChild(text); row.appendChild(nameCell); row.appendChild(multiplierCell); row.appendChild(winCell); userTable.insertBefore(row, userTable.firstChild); }; // 🎲 Вероятностное распределение краша async function getRandomCrashPoint() { if (coinName == null) { coinName = "USDT"; } const convertedAmount = await convertToUSDT(userBet, coinName.toUpperCase()); // 🔹 **Базовые вероятности для множителей** let probabilityTable = [ { range: [1.00, 1.04], chance: 3.7 }, { range: [1.05, 1.15], chance: 7.9 }, { range: [1.16, 1.25], chance: 5.6 }, { range: [1.26, 1.35], chance: 6.6 }, { range: [1.36, 1.45], chance: 3.5 }, { range: [1.46, 1.55], chance: 3.4 }, { range: [1.56, 1.65], chance: 4.0 }, { range: [1.66, 1.75], chance: 3.2 }, { range: [1.76, 1.85], chance: 3.6 }, { range: [1.86, 1.95], chance: 2.1 }, { range: [1.96, 2.05], chance: 1.6 }, { range: [2.06, 2.15], chance: 3.1 }, { range: [2.16, 2.25], chance: 2.7 }, { range: [2.26, 2.50], chance: 2.3 }, { range: [2.51, 3.00], chance: 2.8 }, { range: [3.01, 5.00], chance: 4.5 }, { range: [5.01, 10.00], chance: 3.0 }, { range: [10.01, 20.00], chance: 1.5 }, { range: [20.01, 50.00], chance: 0.7 }, { range: [50.01, 100.00], chance: 0.3 }, { range: [100.01, 300.00], chance: 0.1 } ]; // **Корректировка шансов в зависимости от ставки** let adjustmentFactor = 1.0; if (convertedAmount >= 200) { adjustmentFactor = 3.5; // Крупные ставки - высокие множители редкость } else if (convertedAmount >= 100) { adjustmentFactor = 2.5; } else if (convertedAmount >= 50) { adjustmentFactor = 1.7; } else if (convertedAmount <= 1) { adjustmentFactor = 0.8; // Небольшие ставки = больше шансов на 2x+ } else if (convertedAmount == 0) { adjustmentFactor = 0.5; // Бесплатная игра = больше шансов на 3x - 10x } probabilityTable = probabilityTable.map(entry => ({ ...entry, chance: entry.chance / adjustmentFactor })); // **Нормализуем вероятности (чтобы сумма = 100%)** let totalChance = probabilityTable.reduce((sum, entry) => sum + entry.chance, 0); probabilityTable = probabilityTable.map(entry => ({ ...entry, chance: (entry.chance / totalChance) * 100 })); // 🎲 **Функция выбора случайного множителя по вероятностям** function getCrashMultiplier(probabilityTable) { let rand = Math.random() * 100; let cumulative = 0; for (let entry of probabilityTable) { cumulative += entry.chance; if (rand <= cumulative) { return (entry.range[0] + Math.random() * (entry.range[1] - entry.range[0])).toFixed(2); } } return "1.00"; // На случай ошибки } return getCrashMultiplier(probabilityTable); } cashoutInput.addEventListener("input", (e) => { let value = parseFloat(e.target.value); if (isNaN(value) || value < 1.0) { cashoutInput.value = ""; } else { cashoutValue = parseFloat(value.toFixed(2)); } checkCashoutValue(); }); cashoutInput.addEventListener("blur", (e) => { let value = parseFloat(e.target.value); if (isNaN(value) || value < 1.0) { cashoutInput.value = ""; } else { cashoutValue = parseFloat(value.toFixed(2)); cashoutInput.value = cashoutValue.toFixed(2); } checkCashoutValue(); }); cashoutIncrease.addEventListener("click", () => { cashoutValue += 1; cashoutInput.value = cashoutValue.toFixed(2); checkCashoutValue(); }); cashoutDecrease.addEventListener("click", () => { if (cashoutValue > 2.01) { cashoutValue -= 1; cashoutInput.value = cashoutValue.toFixed(2); } else { cashoutValue = 1.01; cashoutInput.value = 1.01; } checkCashoutValue(); }); const cashoutInputBox = document.getElementById("cashoutInputBox"); function checkCashoutValue() { const cashoutValue = parseFloat(cashoutInput.value); if (isNaN(cashoutValue) || cashoutValue < 1.01) { cashoutInputBox.style.borderColor = "red"; startButton.disabled = true; } else { cashoutInputBox.style.borderColor = ""; cashoutInputBox.style.borderColor = ""; if (!isBetPlaced) { startButton.disabled = true; } else { startButton.disabled = false; } } } const BASE_CURVE_EXPONENT = 1; let curveExponent = BASE_CURVE_EXPONENT; let targetMaxMultiplier = MAX_MULTIPLIER; let targetMaxTime = MAX_TIME; let smoothFactor = 0.05; function gameLoop() { if (!isGameRunning) return; const elapsed = (Date.now() - startTime) / 1000; totalTime = elapsed; const growthFactor = 1 + Math.pow(elapsed, 0.9) * 0.02; currentMultiplier = 1.0 + Math.pow(elapsed, growthFactor) / 22; targetMaxMultiplier = Math.max( targetMaxMultiplier, currentMultiplier + 0.2 ); targetMaxTime = Math.max(targetMaxTime, totalTime + 2); MAX_MULTIPLIER += (targetMaxMultiplier - MAX_MULTIPLIER) * 0.02; MAX_TIME += (targetMaxTime - MAX_TIME) * 0.02; multiplierDisplay.innerText = `${currentMultiplier.toFixed(2)}x`; updateMultiplierPosition(); // ⬅ ВАЖНО: Обновляем позицию во время игры drawGraph(totalTime); if (userCashoutMultiplier !== null) { drawCashoutBox(userCashoutMultiplier); } else if (isRoundActive && isBetPlaced) { const returnAmount = userBet * currentMultiplier; drawReturnBox(returnAmount); } if ( isRoundActive && isBetPlaced && userCashoutMultiplier === null && currentMultiplier >= lockedCashoutValue ) { cashOut(); } randomCashout(currentMultiplier); if (currentMultiplier >= crashPoint) { endGame(); return; } requestAnimationFrame(gameLoop); } async function startGame() { isRoundActive = true; isGameRunning = true; startTime = Date.now(); currentMultiplier = 1.0; crashPoint = await getRandomCrashPoint(); userCashoutMultiplier = null; console.log("Crash at " + crashPoint); if (isBetPlaced) { window.updateStartButtonText(); startButton.disabled = false; } else { window.updateStartButtonText(); startButton.disabled = true; } gameLoop(); } function cashOut() { if (!isGameRunning || userCashoutMultiplier !== null) return; userCashoutMultiplier = currentMultiplier; if (!window.isAutoMode) { startButton.disabled = true; } const userWinAmount = userBet * currentMultiplier; const winAmountCell = document.querySelector(".user-win"); const tokenImage = winAmountCell.querySelector("img"); if (tokenImage) { winAmountCell.style.color = "#00e701"; winAmountCell.innerHTML = ""; winAmountCell.appendChild(tokenImage); const text = document.createTextNode(`${userWinAmount.toFixed(2)}`); winAmountCell.appendChild(text); } const multiplierCell = document.querySelector(".user-multiplier"); multiplierCell.textContent = `${currentMultiplier.toFixed(2)}x`; userVictory(userBet, userCashoutMultiplier); } function endGame() { isGameRunning = false; const isCashout = userCashoutMultiplier !== null; isCrashed = true; const realMultiplier = parseFloat(currentMultiplier.toFixed(2)); addRealMultiplierToHistory(realMultiplier); if (!isCashout && userBet != null) { userDefeat(userBet); } window.updateStartButtonText(); startButton.disabled = true; enableInput(betInput); drawGraph(totalTime, currentMultiplier); if (isCashout) { multiplierDisplay.innerText = `${currentMultiplier.toFixed(2)}x`; multiplierDisplay.style.color = "#f10260"; drawCashoutBox(userCashoutMultiplier); } else { multiplierDisplay.innerText = `${currentMultiplier.toFixed(2)}x`; multiplierDisplay.style.color = "#f10260"; drawCrashBox(); } setTimeout(() => { // Сохраняем результат игры до сброса const isWin = userCashoutMultiplier !== null; resetGame(); isBetweenRounds = true; if (window.isAutoMode && window.autoPlaying) { if (window.remainingBets !== Infinity) { window.remainingBets--; betsInput.value = window.remainingBets; } // Используем сохраненный результат if (isWin) { // On Win логика if (window.onWin.mode === "increase") { const newBet = parseFloat(betInput.value) * (1 + window.onWin.percent / 100); betInput.value = newBet.toFixed(8); } else if (window.onWin.mode === "reset") { betInput.value = window.originalBet.toFixed(8); } } else { // On Loss логика if (window.onLoss.mode === "increase") { const newBet = parseFloat(betInput.value) * (1 + window.onLoss.percent / 100); betInput.value = newBet.toFixed(8); } else if (window.onLoss.mode === "reset") { betInput.value = window.originalBet.toFixed(8); } } if (window.remainingBets === Infinity || window.remainingBets > 0) { placeBet(); disableInputsDuringAutoPlay(); } else { if (window.remainingBets === 0) { window.infinitySign.style.visibility = "visible"; } stopAutoBet(); } } window.updateStartButtonText(); startCountdown(5000, () => { isBetweenRounds = false; startGame(); }); }, 3000); updateMultiplierPosition(); } window.updateStartButtonText = function () { if (window.isAutoMode) { startButton.disabled = false; // Всегда активируем кнопку в авторежиме startButton.innerText = window.autoPlaying ? "Stop Autobet" : "Start Autobet"; return; } if (isRoundActive) { startButton.innerText = "Cashout"; startButton.disabled = false; } else if (isBetweenRounds) { startButton.innerText = isBetPlaced ? "Starting..." : "Bet"; startButton.disabled = isBetPlaced; } else { startButton.innerText = "Bet"; startButton.disabled = false; } }; function drawCashoutBox(cashoutMultiplier) { const boxWidth = 140; const boxHeight = 30; const boxX = Math.min( Math.max(MARGIN + 10, oldCanvasWidth / 2 - boxWidth / 2), oldCanvasWidth - MARGIN - boxWidth - 10 ); const boxY = oldCanvasHeight - MARGIN - boxHeight - 40; const borderRadius = 4; ctx.save(); ctx.shadowColor = "rgba(0, 0, 0, 0.5)"; ctx.shadowBlur = 8; ctx.shadowOffsetX = 3; ctx.shadowOffsetY = 3; ctx.beginPath(); ctx.fillStyle = "#2f4553"; ctx.moveTo(boxX + borderRadius, boxY); ctx.arcTo( boxX + boxWidth, boxY, boxX + boxWidth, boxY + boxHeight, borderRadius ); ctx.arcTo( boxX + boxWidth, boxY + boxHeight, boxX, boxY + boxHeight, borderRadius ); ctx.arcTo(boxX, boxY + boxHeight, boxX, boxY, borderRadius); ctx.arcTo(boxX, boxY, boxX + boxWidth, boxY, borderRadius); ctx.closePath(); ctx.fill(); ctx.shadowColor = "transparent"; ctx.shadowBlur = 0; ctx.shadowOffsetX = 0; ctx.shadowOffsetY = 0; ctx.font = "bold 14px Outfit"; ctx.textAlign = "center"; ctx.textBaseline = "middle"; ctx.fillStyle = "white"; const text = "Cashed Out "; const multiplierText = `${cashoutMultiplier.toFixed(2)}x`; const combinedText = `${text} ${multiplierText}`; const textWidth = ctx.measureText(combinedText).width; const textX = boxX + boxWidth / 2; const textY = boxY + boxHeight / 2; const textOffset = ctx.measureText(text).width; ctx.fillText(text, textX - textWidth / 2 + textOffset / 2, textY); ctx.fillStyle = "#00e701"; ctx.fillText(multiplierText, textX + textOffset / 2, textY); ctx.restore(); } function drawReturnBox(returnAmount) { const boxWidth = 140; const boxHeight = 30; const boxX = Math.min( Math.max(MARGIN + 10, oldCanvasWidth / 2 - boxWidth / 2), oldCanvasWidth - MARGIN - boxWidth - 10 ); const boxY = oldCanvasHeight - MARGIN - boxHeight - 40; const borderRadius = 4; ctx.save(); ctx.shadowColor = "rgba(0, 0, 0, 0.5)"; ctx.shadowBlur = 8; ctx.shadowOffsetX = 3; ctx.shadowOffsetY = 3; ctx.beginPath(); ctx.fillStyle = "#2f4553"; // Цвет фона ctx.moveTo(boxX + borderRadius, boxY); ctx.arcTo( boxX + boxWidth, boxY, boxX + boxWidth, boxY + boxHeight, borderRadius ); ctx.arcTo( boxX + boxWidth, boxY + boxHeight, boxX, boxY + boxHeight, borderRadius ); ctx.arcTo(boxX, boxY + boxHeight, boxX, boxY, borderRadius); ctx.arcTo(boxX, boxY, boxX + boxWidth, boxY, borderRadius); ctx.closePath(); ctx.fill(); ctx.shadowColor = "transparent"; ctx.shadowBlur = 0; ctx.shadowOffsetX = 0; ctx.shadowOffsetY = 0; ctx.font = "bold 14px Outfit"; ctx.textAlign = "center"; ctx.textBaseline = "middle"; ctx.fillStyle = "white"; const text = "Return "; let amountText; if (userBet <= 0.09) { amountText = `${returnAmount.toFixed(8)}`; } else { amountText = `${returnAmount.toFixed(2)}`; } const combinedText = `${text} ${amountText}`; const textWidth = ctx.measureText(combinedText).width; const textX = boxX + boxWidth / 2; const textY = boxY + boxHeight / 2; const textOffset = ctx.measureText(text).width; ctx.fillText(text, textX - textWidth / 2 + textOffset / 2, textY); ctx.fillText(amountText, textX + textOffset / 2, textY); ctx.restore(); } function drawCrashBox() { const boxWidth = 70; const boxHeight = 30; const boxX = Math.min( Math.max(MARGIN + 10, oldCanvasWidth / 2 - boxWidth / 2), oldCanvasWidth - MARGIN - boxWidth - 10 ); const boxY = oldCanvasHeight - MARGIN - boxHeight - 40; const borderRadius = 4; // 🌟 Настройка тени ctx.save(); ctx.shadowColor = "rgba(0, 0, 0, 0.5)"; ctx.shadowBlur = 8; ctx.shadowOffsetX = 3; ctx.shadowOffsetY = 3; // 🎨 Отрисовка прямоугольника со скруглёнными углами ctx.beginPath(); ctx.fillStyle = "#2f4553"; ctx.moveTo(boxX + borderRadius, boxY); ctx.arcTo( boxX + boxWidth, boxY, boxX + boxWidth, boxY + boxHeight, borderRadius ); ctx.arcTo( boxX + boxWidth, boxY + boxHeight, boxX, boxY + boxHeight, borderRadius ); ctx.arcTo(boxX, boxY + boxHeight, boxX, boxY, borderRadius); ctx.arcTo(boxX, boxY, boxX + boxWidth, boxY, borderRadius); ctx.closePath(); ctx.fill(); // 🛡️ Сброс тени для текста ctx.shadowColor = "transparent"; ctx.shadowBlur = 0; ctx.shadowOffsetX = 0; ctx.shadowOffsetY = 0; // 📝 Отрисовка текста ctx.fillStyle = "white"; ctx.font = "bold 14px Outfit"; ctx.textAlign = "center"; ctx.textBaseline = "middle"; ctx.fillText("Crashed", boxX + boxWidth / 2, boxY + boxHeight / 2); ctx.restore(); } function resetGame() { ctx.clearRect(0, 0, oldCanvasWidth, oldCanvasHeight); currentMultiplier = 1.0; totalTime = 0; multiplierDisplay.innerText = "1.00x"; multiplierDisplay.style.color = ""; MAX_TIME = 10; MAX_MULTIPLIER = 2.0; targetMaxTime = MAX_TIME; targetMaxMultiplier = MAX_MULTIPLIER; isCrashed = false; isBetPlaced = false; isRoundActive = false; userCashoutMultiplier = null; userBet = null; lockedCashoutValue = null; enableInput(betInput); cashoutInput.disabled = false; cashoutIncrease.disabled = false; cashoutDecrease.disabled = false; drawGraph(0, 1.0); document.getElementById("total-amount").textContent = 0; } function drawGraph(time) { ctx.clearRect(0, 0, oldCanvasWidth, oldCanvasHeight); drawAxes(); ctx.shadowColor = "transparent"; ctx.shadowBlur = 0; ctx.shadowOffsetX = 0; ctx.shadowOffsetY = 0; // 🎯 Плавное масштабирование без телепортации ctx.beginPath(); ctx.fillStyle = isCrashed ? "#2f4553" : "#ff9d00"; // Сдвиг начальной позиции полосы на 10px вправо ctx.moveTo(MARGIN + OFFSET_X + 10, MARGIN + GRAPH_HEIGHT); let lastX = MARGIN + OFFSET_X + 10; // Сдвиг начальной позиции шарика let lastY = MARGIN + GRAPH_HEIGHT; for (let t = 0; t <= time; t += 0.01) { // 🔄 Коэффициенты масштабирования const scaleX = GRAPH_WIDTH / MAX_TIME; const scaleY = GRAPH_HEIGHT / (MAX_MULTIPLIER - 1.0); const x = MARGIN + OFFSET_X + 10 + t * scaleX; // Сдвиг начальной позиции полосы на 10px const growthFactor = 1 + Math.pow(t, 0.9) * 0.02; const graphMultiplier = 1.0 + Math.pow(t, growthFactor) / 22; const y = MARGIN + GRAPH_HEIGHT - (graphMultiplier - 1.0) * scaleY; ctx.lineTo(x, y); lastX = x; lastY = y; } ctx.lineTo( MARGIN + OFFSET_X + 10 + time * (GRAPH_WIDTH / MAX_TIME), // Сдвиг конечной позиции полосы oldCanvasHeight - MARGIN ); ctx.lineTo(MARGIN + OFFSET_X + 10, oldCanvasHeight - MARGIN); // Сдвиг начальной позиции полосы ctx.closePath(); ctx.fill(); // 🌟 Тень для линии ctx.shadowColor = "rgba(0, 0, 0, 0.4)"; ctx.shadowBlur = 7; ctx.shadowOffsetX = 3; ctx.shadowOffsetY = 5; // Линия графика ctx.beginPath(); ctx.strokeStyle = isCrashed ? "#2f4553" : "white"; ctx.lineWidth = 4; ctx.lineCap = "round"; // Сдвиг начальной позиции линии на 10px вправо ctx.moveTo(MARGIN + OFFSET_X + 10, MARGIN + GRAPH_HEIGHT); for (let t = 0; t <= time; t += 0.1) { const scaleX = GRAPH_WIDTH / MAX_TIME; const scaleY = GRAPH_HEIGHT / (MAX_MULTIPLIER - 1.0); const x = MARGIN + OFFSET_X + 10 + t * scaleX; // Сдвиг начальной позиции линии на 10px const growthFactor = 1 + Math.pow(t, 0.9) * 0.02; const graphMultiplier = 1.0 + Math.pow(t, growthFactor) / 22; const y = MARGIN + GRAPH_HEIGHT - (graphMultiplier - 1.0) * scaleY; ctx.lineTo(x, y); } ctx.stroke(); // 🔵 Шарик на конце линии ctx.beginPath(); ctx.arc(lastX, lastY, 5, 0, 2 * Math.PI); // Шарик уже сдвинут на 10px ctx.fillStyle = isCrashed ? "#2f4553" : "white"; ctx.fill(); if (isCrashed) { drawCrashBox(); } } function drawAxes() { ctx.strokeStyle = "#fff"; ctx.lineWidth = 4; ctx.font = "9px Outfit"; ctx.fillStyle = "#fff"; // Ось X ctx.textAlign = "center"; ctx.textBaseline = "top"; for (let i = 0; i <= OX_LABELS; i++) { const x = MARGIN + OFFSET_X + (i / OX_LABELS) * GRAPH_WIDTH; if (i === 0) continue; const label = i === OX_LABELS ? `Total ${parseInt(totalTime)}s` : `${(i * (MAX_TIME / OX_LABELS)).toFixed(0)}s`; ctx.fillText(label, x, oldCanvasHeight - 20); } const boxWidth = 35; // Ширина блока const boxHeight = 20; // Высота блока const radius = 5; // Радиус закругления // Оси ctx.strokeStyle = "#2f4553"; // Устанавливаем нужный цвет ctx.beginPath(); const axisX = MARGIN - (boxWidth / 2) + OFFSET_X; // Смещаем линию в центр блоков ctx.moveTo(axisX, MARGIN); ctx.lineTo(axisX, oldCanvasHeight - MARGIN); ctx.stroke(); // Ось Y с закругленными прямоугольниками ctx.textAlign = "center"; ctx.textBaseline = "middle"; for (let i = 0; i < OY_LABELS; i++) { const y = MARGIN + GRAPH_HEIGHT - (i / (OY_LABELS - 1)) * GRAPH_HEIGHT; const label = `${( 1.0 + (i * (MAX_MULTIPLIER - 1.0)) / (OY_LABELS - 1) ).toFixed(1)}x`; const boxX = MARGIN - boxWidth - 0 + OFFSET_X; // Позиция блока по X // Рисуем закругленный прямоугольник ctx.shadowBlur = 0; ctx.shadowColor = "transparent"; ctx.shadowOffsetX = 0; ctx.shadowOffsetY = 0; ctx.fillStyle = "#253742"; drawRoundedRect( ctx, boxX, y - boxHeight / 2, boxWidth, boxHeight, radius ); // Рисуем текст в центре блока ctx.fillStyle = "#fff"; ctx.fillText(label, boxX + boxWidth / 2, y); } } function drawRoundedRect(ctx, x, y, width, height, radius) { ctx.beginPath(); ctx.moveTo(x + radius, y); ctx.lineTo(x + width - radius, y); ctx.quadraticCurveTo(x + width, y, x + width, y + radius); ctx.lineTo(x + width, y + height - radius); ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height); ctx.lineTo(x + radius, y + height); ctx.quadraticCurveTo(x, y + height, x, y + height - radius); ctx.lineTo(x, y + radius); ctx.quadraticCurveTo(x, y, x + radius, y); ctx.closePath(); ctx.fill(); } function drawCountdownTimer(progress) { ctx.shadowColor = "transparent"; ctx.shadowBlur = 0; ctx.shadowOffsetX = 0; ctx.shadowOffsetY = 0; const boxHeight = 30; const boxY = oldCanvasHeight / 2 + 30; const boxWidth = 150; const boxX = Math.max(MARGIN + OFFSET_X, oldCanvasWidth / 2 - boxWidth / 2); ctx.clearRect(boxX - 10, boxY - 10, boxWidth + 20, boxHeight + 20); const gradient = ctx.createLinearGradient( boxX + boxWidth, boxY, boxX, boxY ); gradient.addColorStop(0, "#2f4553"); gradient.addColorStop(progress, "#2f4553"); gradient.addColorStop(progress, "#ff9d00"); gradient.addColorStop(1, "#ff9d00"); ctx.fillStyle = gradient; ctx.beginPath(); ctx.roundRect(boxX, boxY, boxWidth, boxHeight, 4); ctx.fill(); ctx.font = "bold 16px Outfit"; ctx.fillStyle = "#ffffff"; ctx.textAlign = "center"; ctx.textBaseline = "middle"; ctx.fillText("Starting in", boxX + boxWidth / 2, boxY + boxHeight / 2); } function startCountdown(duration, callback) { updateMultiplierPosition(); const startTime = Date.now(); populateUserTable(); function animate() { const elapsed = Date.now() - startTime; const progress = Math.min(elapsed / duration, 1); drawCountdownTimer(progress); if (isBetPlaced) { startButton.innerText = "Starting..."; startButton.disabled = true; } else { window.updateStartButtonText(); startButton.disabled = false; } if (progress < 1) { requestAnimationFrame(animate); } else { updateMultiplierPosition(); callback(); } } animate(); } historyContainer.style.display = "flex"; historyContainer.style.justifyContent = "flex-end"; historyContainer.style.alignItems = "center"; historyContainer.style.width = "100%"; historyContainer.style.padding = "10px"; historyContainer.style.paddingRight = "25px"; function generateRandomMultiplier() { const random = Math.random(); if (random < 0.7) { return (2 + Math.random() * 1).toFixed(2); } else { return (1 + Math.random() * 14).toFixed(2); } } function updateHistoryDOM(withAnimation = true) { historyContainer.innerHTML = ""; historyData.forEach((multiplier, index) => { const multiplierBox = document.createElement("div"); multiplierBox.classList.add("history-item"); multiplierBox.style.backgroundColor = multiplier < 2 ? "#2f4553" : "#00e701"; multiplierBox.style.color = multiplier < 2 ? "white" : "black"; multiplierBox.textContent = `${multiplier}x`; if (index === historyData.length - 1 && withAnimation) { multiplierBox.classList.add("slide-in"); } historyContainer.appendChild(multiplierBox); }); const extraItems = Array.from(historyContainer.children).slice( 0, historyData.length - 3 ); extraItems.forEach((item) => { item.classList.add("slide-out"); setTimeout(() => item.remove(), 500); }); } function addRealMultiplierToHistory(multiplier) { if (historyData.length >= 3) { historyData.shift(); } historyData.push(multiplier); updateHistoryDOM(true); saveHistoryToLocalStorage(); } for (let i = 0; i < 3; i++) { historyData.push(parseFloat(generateRandomMultiplier())); } function saveHistoryToLocalStorage() { localStorage.setItem("historyData", JSON.stringify(historyData)); } function loadHistoryFromLocalStorage() { const savedHistory = localStorage.getItem("historyData"); historyData.length = 0; if (savedHistory) { historyData.push(...JSON.parse(savedHistory)); while (historyData.length > 3) { historyData.shift(); } } else { for (let i = 0; i < 3; i++) { historyData.push(parseFloat(generateRandomMultiplier())); } saveHistoryToLocalStorage(); } updateHistoryDOM(false); } function addRealMultiplierToHistory(multiplier) { if (historyData.length >= 3) { historyData.shift(); } historyData.push(multiplier); updateHistoryDOM(); saveHistoryToLocalStorage(); } loadHistoryFromLocalStorage(); resetGame(); startCountdown(5000, () => { startGame(); }); const onlineElement = document.getElementById("total-players"); onlineElement.textContent = localStorage.getItem("total-players") || 140; function updateOnlineCount() { let onlineCount = parseInt(onlineElement.textContent); const step = Math.floor(Math.random() * 7) - 3; onlineCount += step; if (onlineCount < 80) onlineCount = 80; if (onlineCount > 300) onlineCount = 300; onlineElement.textContent = onlineCount; localStorage.setItem("total-players", onlineCount.toString()); } function startOnlineUpdates() { const minDelay = 3000; const maxDelay = 10000; function scheduleUpdate() { const delay = Math.floor(Math.random() * (maxDelay - minDelay + 1)) + minDelay; setTimeout(() => { updateOnlineCount(); scheduleUpdate(); }, delay); } scheduleUpdate(); } startOnlineUpdates(); async function updateFixedRates() { try { const rates = await fetchCryptoRates(); // Получаем актуальные курсы if (rates) { for (const token in rates) { if (fixedRates.hasOwnProperty(token)) { fixedRates[token] = rates[token]; // Обновляем курс } } console.log("Курсы обновлены:", fixedRates); } } catch (error) { console.error("Ошибка обновления курсов:", error); } } function formatTokenAmount(amount) { // Если значение целое – возвращаем с двумя знаками после запятой if (amount % 1 === 0) { return amount.toFixed(2); } let decimals; if (amount < 0.0001) { decimals = 8; } else if (amount < 0.01) { decimals = Math.floor(Math.random() * 3) + 6; // 6-8 знаков } else if (amount < 1) { decimals = Math.floor(Math.random() * 4) + 3; // 3-6 знаков } else { decimals = Math.floor(Math.random() * 3) + 2; // 2-4 знака } return amount.toFixed(decimals); } function generateRealisticUsdBet() { let rawBet; // 80% ставок будут в диапазоне 10-50$, 20% - случайные выше if (Math.random() < 0.8) { rawBet = 10 + Math.floor(Math.random() * 41); // От 10 до 50$ } else { rawBet = 50 + (-Math.log(Math.random()) * 30); // Реже встречаются крупные ставки до 200$ rawBet = Math.min(rawBet, 200); } // Округляем красиво if (rawBet < 50) { rawBet = Math.round(rawBet); // Мелкие ставки - целые } else { rawBet = Math.round(rawBet / 5) * 5; // Крупные - кратные 5 } return rawBet; } async function generateRandomUsers() { await updateFixedRates(); // Перед генерацией пользователей обновляем курсы const users = []; const numUsers = 100; const tokens = [ { name: "BTC", weight: 15 }, { name: "ETH", weight: 15 }, { name: "USDT", weight: 25 }, { name: "BNB", weight: 10 }, { name: "LTC", weight: 5 }, { name: "SOL", weight: 5 }, { name: "MATIC", weight: 5 }, { name: "TON", weight: 25 }, { name: "USDC", weight: 5 }, { name: "XRP", weight: 5 }, ]; const totalWeight = tokens.reduce((acc, token) => acc + token.weight, 0); for (let i = 0; i < numUsers; i++) { const id = Math.floor(Math.random() * (99999999 - 11111111 + 1)) + 11111111; const rand = Math.random() * totalWeight; let cumulative = 0; let chosenToken = tokens[0].name; for (const token of tokens) { cumulative += token.weight; if (rand < cumulative) { chosenToken = token.name; break; } } let usdBet = generateRealisticUsdBet(); // Используем актуальные курсы для расчета let tokenAmount = usdBet / fixedRates[chosenToken]; tokenAmount = formatTokenAmount(tokenAmount); users.push({ name: `${id}`, multiplier: "-", token: chosenToken, usdBet: usdBet, tokenBet: tokenAmount, winAmount: usdBet, }); } //users.sort((a, b) => b.winAmount - a.winAmount); return users; } async function populateUserTable() { const userTable = document.getElementById("user-table"); userTable.innerHTML = ""; // Очистка таблицы const users = await generateRandomUsers(); // Генерация пользователей const topUsers = users.slice(0, 30); // Берем топ-30 для таблицы const topAmount = topUsers.reduce((sum, user) => sum + user.winAmount, 0); // Добавляем случайный процент (5-15%) сверху const additionalAmount = topAmount * (0.05 + Math.random() * 0.10); const finalTotalAmount = topAmount + additionalAmount; function animateTotalAmount(targetAmount) { let currentAmount = 0; // Начинаем с 0 const duration = 4500; // Общая длительность анимации (5 секунд) const updates = 12; // Количество обновлений (примерно 12 раз за 5 секунд) const intervalTime = duration / updates; // Интервал между обновлениями const minStep = targetAmount * 0.06; // Минимальный шаг (6% от итоговой суммы) const maxStep = targetAmount * 0.12; // Максимальный шаг (12% от итоговой суммы) const interval = setInterval(() => { const step = minStep + Math.random() * (maxStep - minStep); // Случайный шаг 6-12% currentAmount += step; if (currentAmount >= targetAmount) { currentAmount = targetAmount; // Останавливаем на финальном значении clearInterval(interval); } document.getElementById("total-amount").textContent = currentAmount.toFixed(2); }, intervalTime); // Обновления каждые 5с / 12 ≈ 400 мс } // Запускаем анимацию animateTotalAmount(finalTotalAmount); let index = 0; const interval = setInterval(() => { if (index >= topUsers.length) { clearInterval(interval); // Останавливаем интервал, когда все пользователи добавлены return; } // Добавляем нового пользователя const user = topUsers[index]; const row = document.createElement("div"); row.classList.add("user-row"); // Сохраняем USD-ставку и токен в data-атрибутах для сортировки и дальнейших пересчётов row.dataset.usdBet = user.winAmount; row.dataset.token = user.token; const nameCell = document.createElement("div"); nameCell.classList.add("user-name"); nameCell.innerHTML = `${user.name}id`; const multiplierCell = document.createElement("div"); multiplierCell.classList.add("user-multiplier"); multiplierCell.textContent = user.multiplier; const winCell = document.createElement("div"); winCell.classList.add("user-win"); // Вместо знака $ добавляем картинку токена и значение ставки (в единицах токена) const img = document.createElement("img"); img.src = `../Images/${user.token}.png`; img.alt = user.token; img.style.width = "16px"; img.style.height = "16px"; img.style.marginRight = "5px"; winCell.appendChild(img); const text = document.createTextNode(user.tokenBet); winCell.appendChild(text); row.appendChild(nameCell); row.appendChild(multiplierCell); row.appendChild(winCell); userTable.appendChild(row); // Сортируем таблицу после добавления нового пользователя //sortUserTable(); setTimeout(() => { row.classList.add("visible"); }, 10); index++; }, 100); // Задержка для плавного добавления } function sortUserTable() { const userTable = document.getElementById("user-table"); const rows = Array.from(userTable.querySelectorAll(".user-row")); // Сортировка по USD-ставке (хранимой в data-атрибуте) rows.sort((a, b) => { const aUsd = parseFloat(a.dataset.usdBet); const bUsd = parseFloat(b.dataset.usdBet); return bUsd - aUsd; }); userTable.innerHTML = ""; rows.forEach((row) => { userTable.appendChild(row); }); } function calculateCashoutProbability(userWinAmount, maxWinAmount) { const baseProbability = 0.001; // Базовая вероятность return (userWinAmount / maxWinAmount) * baseProbability; } function formatCashoutTokenBet(amount) { // Получаем целую часть и её строковое представление const intPart = Math.floor(amount); const intStr = intPart.toString(); // Вычисляем, сколько цифр можно показать после запятой, чтобы общее число цифр не превышало 8 const allowedDecimals = 8 - intStr.length; // Если целая часть уже занимает 8 и более цифр, возвращаем её полностью if (allowedDecimals <= 0) { return intStr; } // Транслируем число: умножаем на 10^(allowedDecimals), отбрасываем дробь и делим обратно const factor = Math.pow(10, allowedDecimals); const truncated = Math.floor(amount * factor) / factor; // Преобразуем результат в строку // Если число целое (нет дробной части) — просто возвращаем строку let truncatedStr = truncated.toString(); if (truncatedStr.indexOf('.') === -1) { return truncatedStr; } // Если есть дробная часть — отбрасываем лишние нули в конце (если они есть) truncatedStr = truncatedStr.replace(/(.\d*?[1-9])0+$/, '$1').replace(/.$/, ''); return truncatedStr; } function randomCashout(currentMultiplier) { if (currentMultiplier <= 1.0) return; const userRows = document.querySelectorAll(".user-row"); // Находим максимальную ставку (USD-эквивалент) среди пользователей let maxUsdBet = 0; userRows.forEach((row) => { const usdBet = parseFloat(row.dataset.usdBet); if (usdBet > maxUsdBet) { maxUsdBet = usdBet; } }); // Для каждого пользователя проверяем возможность cashout userRows.forEach((row) => { const multiplierCell = row.querySelector(".user-multiplier"); const winCell = row.querySelector(".user-win"); if (multiplierCell.textContent === "-") { const usdBet = parseFloat(row.dataset.usdBet); const cashoutProbability = calculateCashoutProbability(usdBet, maxUsdBet); if (Math.random() < cashoutProbability) { // Обновляем множитель multiplierCell.textContent = `${currentMultiplier.toFixed(2)}x`; // Пересчитываем USD-ставку const newUsdBet = usdBet * currentMultiplier; row.dataset.usdBet = newUsdBet; // Пересчитываем ставку в токенах const token = row.dataset.token; let newTokenBet = newUsdBet / fixedRates[token]; // Используем нашу новую функцию форматирования: newTokenBet = formatCashoutTokenBet(newTokenBet); // Обновляем отображение: вставляем картинку токена и новое значение winCell.innerHTML = ""; const img = document.createElement("img"); img.src = `../Images/${token}.png`; img.alt = token; img.style.width = "16px"; img.style.height = "16px"; img.style.marginRight = "5px"; winCell.appendChild(img); const text = document.createTextNode(newTokenBet); winCell.appendChild(text); // Выделяем выигрыш зелёным цветом winCell.style.color = "#00e701"; } } }); } populateUserTable(); async function userVictory(bet, coefficient) { balance -= userBet; let iconPathTable = await getUserValue(telegramUserId, 'iconPath'); gamesPlayed2++; updateRefferedCommissionToGifter(userBet); updateRefferedSUMMCommission(userBet); winAmountGlobal = (userBet * userCashoutMultiplier); WinCoef = userCashoutMultiplier; balance = parseFloat(balance) + parseFloat(userBet) * parseFloat(userCashoutMultiplier); UpdateWageredLostWon((userBet * userCashoutMultiplier), "win"); UpdateLastBiggestBet(telegramUserId, (userBet * userCashoutMultiplier)); const gameResult = `Выигрыш ${(userBet * userCashoutMultiplier).toFixed(8)}$`; addBetToMyBets({ name: 'Crash', result: gameResult, currency: iconPathTable }); gamesWon++; saveGameData(); document.getElementById('balance').textContent = balance.toFixed(8); } async function userDefeat(bet) { console.log(`Поражение! Ставка: ${bet}. Проигрыш.`); let iconPathTable = await getUserValue(telegramUserId, 'iconPath'); gamesPlayed2++; updateRefferedCommissionToGifter(userBet); updateRefferedSUMMCommission(userBet); const bet5 = userBet * (-1); const gameResult = `Проигрыш ${bet5.toFixed(8)}$`; addBetToMyBets({ name: 'Crash', result: gameResult, currency: iconPathTable }); balance -= userBet; UpdateWageredLostWon(userBet, "lose"); UpdateLastBiggestBet(telegramUserId, -userBet); gamesLost++; saveGameData(); document.getElementById('balance').textContent = balance.toFixed(8); } }); const manualModeBtn = document.getElementById("manual-mode-btn"); const autoModeBtn = document.getElementById("auto-mode-btn"); const betButton = document.getElementById("start-btn"); const autoSettings = document.getElementById("auto-settings"); const betsInput = document.getElementById("bets-input"); function setMode(mode) { if (window.isBetPlaced) return; if (mode === "manual") { manualModeBtn.classList.add("active"); autoModeBtn.classList.remove("active"); autoSettings.style.display = "none"; stopAutoBet(); window.isAutoMode = false; window.updateStartButtonText(); } else if (mode === "auto") { autoModeBtn.classList.add("active"); manualModeBtn.classList.remove("active"); betButton.innerText = "Start Autobet"; autoSettings.style.display = "block"; window.isAutoMode = true; window.updateStartButtonText(); } } function disableInputsDuringAutoPlay() { document.getElementById('manual-mode-btn').disabled = true; document.getElementById('auto-mode-btn').disabled = true; document.getElementById('bets-input').disabled = true; document.getElementById('cashout-input').disabled = true; document.getElementById('cashout-increase').disabled = true; document.getElementById('cashout-decrease').disabled = true; document.getElementById('bets-decrease').disabled = true; document.getElementById('bets-increase').disabled = true; document.getElementById('reset-btn').disabled = true; document.getElementById('increase-btn').disabled = true; document.getElementById('increase-input').disabled = true; document.getElementById('loss-reset-btn').disabled = true; document.getElementById('loss-increase-btn').disabled = true; document.getElementById('loss-increase-input').disabled = true; document.getElementById('bet').disabled = true; document.getElementById('halve').disabled = true; document.getElementById('double').disabled = true; console.log("CLOSE"); } function enableInputsAfterAutoPlay() { document.getElementById('manual-mode-btn').disabled = false; document.getElementById('auto-mode-btn').disabled = false; document.getElementById('bets-input').disabled = false; document.getElementById('cashout-input').disabled = false; document.getElementById('cashout-increase').disabled = false; document.getElementById('cashout-decrease').disabled = false; document.getElementById('bets-decrease').disabled = false; document.getElementById('bets-increase').disabled = false; document.getElementById('reset-btn').disabled = false; document.getElementById('increase-btn').disabled = false; document.getElementById('increase-input').disabled = false; document.getElementById('loss-reset-btn').disabled = false; document.getElementById('loss-increase-btn').disabled = false; document.getElementById('loss-increase-input').disabled = false; document.getElementById('bet').disabled = false; document.getElementById('halve').disabled = false; document.getElementById('double').disabled = false; console.log("OPEN"); } window.onWin = { mode: 'reset', percent: 1 }; window.onLoss = { mode: 'reset', percent: 1 }; window.originalBet = 0; // Модифицируем startAutoBet function startAutoBet() { if (!window.isAutoMode || window.autoPlaying) return; disableInputsDuringAutoPlay(); window.autoPlaying = true; const inputValue = parseInt(betsInput.value); window.remainingBets = inputValue === 0 ? Infinity : inputValue || 1; betsInput.value = inputValue === 0 ? 0 : window.remainingBets; betButton.textContent = "Stop Autobet"; window.originalBet = parseFloat(betInput.value) || 0; // Сохраняем исходную ставку if (window.isBetweenRounds && !window.isBetPlaced) { placeBet(); } } function stopAutoBet() { window.autoPlaying = false; enableInputsAfterAutoPlay(); betButton.textContent = "Start Autobet"; console.log("Auto betting stopped."); window.updateStartButtonText(); } manualModeBtn.addEventListener("click", () => setMode('manual')); autoModeBtn.addEventListener("click", () => setMode('auto')); function checkBetsInput() { const input = document.getElementById("bets-input"); window.infinitySign = document.getElementById("infinity-sign"); if (input.value === "" || input.value === "0") { infinitySign.style.visibility = "visible"; } else { infinitySign.style.visibility = "hidden"; } } function handleBlur() { const input = document.getElementById("bets-input"); if (input.value === "") { input.value = "0"; } } function handleFocus() { const input = document.getElementById("bets-input"); const infinitySign = document.getElementById("infinity-sign"); if (input.value === "0") { input.value = ""; } infinitySign.style.visibility = "hidden"; } function decreaseBets() { const input = document.getElementById("bets-input"); const infinitySign = document.getElementById("infinity-sign"); // Уменьшаем значение до 0 if (input.value === "∞" || parseInt(input.value) > 0) { let newValue = parseInt(input.value) - 1; if (newValue < 0) { newValue = 0; } input.value = newValue.toString(); // Если значение стало 0, показываем бесконечность if (newValue === 0) { infinitySign.style.visibility = "visible"; } else { infinitySign.style.visibility = "hidden"; } } } function increaseBets() { const input = document.getElementById("bets-input"); const infinitySign = document.getElementById("infinity-sign"); if (input.value === "∞") { input.value = "1"; infinitySign.style.visibility = "hidden"; } else { let newValue = parseInt(input.value) + 1; input.value = newValue.toString(); // Если значение больше 0, скрываем бесконечность if (newValue > 0) { infinitySign.style.visibility = "hidden"; } } } function setOnWinMode(mode) { const resetBtn = document.getElementById("reset-btn"); const increaseBtn = document.getElementById("increase-btn"); const increaseInput = document.getElementById("increase-input"); if (mode === "reset") { resetBtn.classList.add("selected"); increaseBtn.classList.remove("selected"); increaseInput.disabled = true; increaseInput.value = "0"; window.onWin.mode = 'reset'; } else if (mode === "increase") { increaseBtn.classList.add("selected"); resetBtn.classList.remove("selected"); increaseInput.disabled = false; increaseInput.focus(); window.onWin.mode = 'increase'; window.onWin.percent = parseFloat(increaseInput.value) || 0; } } function setOnLossMode(mode) { const resetBtn = document.getElementById('loss-reset-btn'); const increaseBtn = document.getElementById('loss-increase-btn'); const lossInput = document.getElementById('loss-increase-input'); if (mode === 'reset') { resetBtn.classList.add('selected'); increaseBtn.classList.remove('selected'); lossInput.disabled = true; lossInput.value = "0"; window.onLoss.mode = 'reset'; } else if (mode === 'increase') { increaseBtn.classList.add('selected'); resetBtn.classList.remove('selected'); lossInput.disabled = false; lossInput.focus(); window.onLoss.mode = 'increase'; window.onLoss.percent = parseFloat(lossInput.value) || 0; } } function checkIncreaseInput() { const input = document.getElementById('increase-input'); let value = input.value.replace(/[^0-9.]/g, ''); let parts = value.split('.'); if (parts.length > 1) { value = parts[0] + '.' + parts[1].slice(0, 2); } input.value = value; window.onWin.percent = parseFloat(value) || 0; } function checkLossIncreaseInput() { const input = document.getElementById('loss-increase-input'); let value = input.value.replace(/[^0-9.]/g, ''); let parts = value.split('.'); if (parts.length > 1) { value = parts[0] + '.' + parts[1].slice(0, 2); } input.value = value; window.onLoss.percent = parseFloat(value) || 0; }