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;
}