From 1f509dbffbfffd6be1a24437036726b919fa0286 Mon Sep 17 00:00:00 2001 From: Degradin Date: Thu, 26 Dec 2024 03:08:41 +0300 Subject: [PATCH] v0.0.4 --- bot.js | 178 ++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 120 insertions(+), 58 deletions(-) diff --git a/bot.js b/bot.js index c38d786..e9cec3a 100644 --- a/bot.js +++ b/bot.js @@ -375,7 +375,7 @@ bot.hears('🏗️ Предприятия', async (ctx) => { } else { buttons.push([{ text: '🗄️ Построить склад', callback_data: 'buy_warehouse' }]); } - + buttons.push([{ text: '💰 Продать ресурсы', callback_data: 'sell_resources' }]) // Возвращаем меню с кнопками return await ctx.reply(message, Markup.inlineKeyboard(buttons).resize()); }); @@ -405,7 +405,7 @@ bot.action('enterprise_menu', async (ctx) => { } else { buttons.push([{ text: '🗄️ Построить склад', callback_data: 'buy_warehouse' }]); } - + buttons.push([{ text: '💰 Продать ресурсы', callback_data: 'sell_resources' }]) // Возвращаем меню с кнопками return await ctx.editMessageText(message, Markup.inlineKeyboard(buttons).resize()); }); @@ -463,7 +463,7 @@ bot.action('my_enterprises', async (ctx) => { buttons.push(enterpriseButtons); } message += '\n\n[📈 - Улучшить]\n[🛻 - Нанять грузовик]\n 🚛 - Улучшить грузовик\n[💰 - Продать ресурсы с предприятия]\n[🔄 - Перевезти все на склад]' - buttons.push([{ text: '⬅️ Назад', callback_data: 'back_to_menu' }]); + buttons.push([{ text: '⬅️ Назад', callback_data: 'enterprise_menu' }]); return await ctx.editMessageText(message, Markup.inlineKeyboard(buttons).resize()); }); @@ -495,7 +495,7 @@ bot.action('build_enterprise', async (ctx) => { for (const resource of resourcePrices) { const resourceName = getEnterpriseEmoji(resource.resource); - message += `${resourceName}: ${Math.round(resource.price)} монет\n`; + message += `${resourceName}: ${Math.round(resource.price)} руб.\n`; // Генерируем кнопки для каждого ресурса buttons.push([ @@ -584,7 +584,7 @@ bot.action('buy_warehouse', async (ctx) => { }) await user.update({ money: user.money - 500000 }) - return await ctx.editMessageText(`Вы успешно купили единый склад!`) + return await ctx.reply(`Вы успешно купили единый склад!`) }) // Управление складом @@ -607,27 +607,12 @@ bot.action('manage_warehouse', async (ctx) => { message += `💎 Алмазы: ${warehouse.diamond || 0}\n`; const buttons = [ - [{ text: '➕ Перевести ресурсы', callback_data: 'transfer_resources' }], - [{ text: '📤 Продать со склада', callback_data: 'sell_from_warehouse' }], - [{ text: '🚚 Купить транспорт', callback_data: 'buy_truck' }] + [{ text: '➕ Перевести ресурсы', callback_data: 'transfer_resources' }] ]; - + buttons.push([{ text: '⬅️ Назад', callback_data: 'enterprise_menu' }]); return await ctx.editMessageText(message, Markup.inlineKeyboard(buttons).resize()); }); -// Управление предприятием -bot.action(/manage_(\d+)/, async (ctx) => { - let enterpriseId = ctx.match[1] - let enterprise = await EnterpriseModel.findByPk(enterpriseId) - - if (!enterprise) return await ctx.reply(`Предприятие не найдено.`) - const buttons = [ - [{ text: 'Продать ресурсы', callback_data: 'sell_resources' }], - [{ text: 'Нанять грузовик', callback_data: 'hire_truck' }] - ]; - // Логика управления предприятием (например, прокачка или продажа ресурсов) - return await ctx.reply(`Вы управляете предприятием ${enterprise.name} (ID: ${enterprise.id}).`, Markup.inlineKeyboard(buttons).resize()) -}) bot.action('transfer_resources', async (ctx) => { const user = await UserModel.findByPk(ctx.from.id); const warehouse = await WarehouseModel.findOne({ where: { playerId: user.telegram_id } }); @@ -647,7 +632,7 @@ bot.action('transfer_resources', async (ctx) => { const buttons = enterprises.map(ent => { return [{ text: `🏭 ${ent.name}`, callback_data: `transfer_from_${ent.id}` }]; }); - + buttons.push([{ text: '⬅️ Назад', callback_data: 'enterprise_menu' }]); return await ctx.editMessageText(message, Markup.inlineKeyboard(buttons).resize()); }); @@ -738,7 +723,7 @@ bot.action(/upgrade_(\d+)/, async (ctx) => { let upgradeCost = enterprise.level * 100 // Стоимость улучшения зависит от уровня if (user.balance < upgradeCost) { - return await ctx.reply(`У вас недостаточно средств для прокачки предприятия. Необходимо ${upgradeCost} монет.`) + return await ctx.reply(`У вас недостаточно средств для прокачки предприятия. Необходимо ${upgradeCost} руб.`) } // Прокачка: повышение уровня и эффективности @@ -761,18 +746,29 @@ bot.action('sell_resources', async (ctx) => { }); if (enterprises.length === 0) { - return await ctx.reply('У вас нет предприятий для продажи ресурсов.'); + return await ctx.reply('❌ У вас нет предприятий для продажи ресурсов.'); } - let message = 'Список ваших предприятий и их ресурсы:\n\n'; + let message = `📜 Список ваших предприятий и их ресурсы:\n\n`; enterprises.forEach((enterprise, index) => { - message += `${index + 1}. ${enterprise.name} (${enterprise.resourceType}): ${enterprise.currentResources} единиц\n`; + message += `${index + 1}. ${enterprise.name} (${enterprise.resourceType}): ${enterprise.currentResources} единиц\n`; }); - message += `\nЧтобы продать ресурсы, используйте команду:\n/sellres <номер_предприятия> <количество>\nПример: /sellres 1 50`; - return await ctx.reply(message); + message += `\n📦 Продажа ресурсов:\n`; + message += `• Для продажи ресурсов с предприятия используйте команду:\n/sellres [номер_предприятия] [количество]\nПример: /sellres 1 50\n\n`; + message += `• Для продажи ресурсов со склада используйте команду:\n/sellstorage [тип_ресурса (wood/coal/oil/metall/gold/diamond)] [количество]\nПример: /sellstorage wood 10`; + + return await ctx.reply(message, { + parse_mode: 'HTML', + reply_markup: { + inline_keyboard: [ + [{ text: '↩ Назад', callback_data: 'enterprise_menu' }] + ] + } + }); }); + // Обработка продажи ресурсов bot.command('sellres', async (ctx) => { const user = await UserModel.findByPk(ctx.from.id); @@ -819,9 +815,9 @@ bot.command('sellres', async (ctx) => { user.money += totalSale; await user.save(); - // Инфляция: уменьшение цены ресурса + // Ослабленная инфляция resourcePrice.price = Math.round( - resourcePrice.price * Math.exp(-resourcePrice.fluctuationRate * amount) + resourcePrice.price * Math.exp(-resourcePrice.fluctuationRate * (amount / 10)) // Дробное уменьшение инфляции ); // Гарантируем, что цена не упадет ниже 50% от базовой цены @@ -830,28 +826,50 @@ bot.command('sellres', async (ctx) => { await resourcePrice.save(); return await ctx.reply( - `Вы продали ${amount} единиц ${enterprise.resourceType} с предприятия ${enterprise.name} за ${totalSale} монет.\nТекущая цена за единицу: ${resourcePrice.price.toFixed(0)} монет.` + `Вы продали ${amount} единиц ${enterprise.resourceType} с предприятия ${enterprise.name} за ${totalSale} руб.\nТекущая цена за единицу: ${resourcePrice.price.toFixed(0)} руб.` ); }); -// Восстановление цен ресурсов const recoverResourcePrices = async () => { const resources = await ResourcePriceModel.findAll(); for (const resource of resources) { + // Определяем случайное колебание в диапазоне [-maxFluctuation, maxFluctuation] + const maxFluctuation = resource.basePrice * 0.03; // 3% от базовой цены + const priceFluctuation = (Math.random() * 2 - 1) * maxFluctuation; + + // Применяем колебание + resource.price = Math.round(resource.price + priceFluctuation); + + // Если цена выше базовой, шанс на её снижение + if (resource.price > resource.basePrice) { + const chanceToDrop = 0.6; // 60% шанс на снижение + if (Math.random() < chanceToDrop) { + resource.price -= Math.round(resource.basePrice * 0.01); // Снижение на 1% базовой цены + } + } + + // Если цена ниже базовой, восстанавливаем с учётом recoveryRate if (resource.price < resource.basePrice) { resource.price = Math.min( - resource.price + resource.basePrice * resource.recoveryRate, + Math.round(resource.price + resource.basePrice * resource.recoveryRate), resource.basePrice // Не превышать базовую цену ); - await resource.save(); } + + // Гарантируем, что цена остаётся в диапазоне [50% basePrice, 150% basePrice] + resource.price = Math.max(resource.price, Math.round(resource.basePrice * 0.5)); // Минимум + resource.price = Math.min(resource.price, Math.round(resource.basePrice * 1.5)); // Максимум + + await resource.save(); // Сохраняем после всех корректировок } }; + + // Запускаем процесс восстановления цен каждые 15 минут -setInterval(recoverResourcePrices, 15 * 60 * 1000); +setInterval(recoverResourcePrices, 5 * 1000); bot.action(/sell_all_(\d+)/, async (ctx) => { const enterpriseId = ctx.match[1]; @@ -903,9 +921,9 @@ bot.action(/confirm_ressell_(\d+)/, async (ctx) => { await user.save(); await enterprise.save(); - // Инфляция: уменьшение цены ресурса + // Ослабленная инфляция resourcePrice.price = Math.round( - resourcePrice.price * Math.exp(-resourcePrice.fluctuationRate * amount) + resourcePrice.price * Math.exp(-resourcePrice.fluctuationRate * (amount / 10)) // Дробное уменьшение инфляции ); // Гарантируем, что цена не упадет ниже 50% от базовой цены @@ -913,7 +931,64 @@ bot.action(/confirm_ressell_(\d+)/, async (ctx) => { await resourcePrice.save(); - await ctx.reply(`Вы успешно продали ${currentResources} ед. ${resourceType} за ${totalPrice} руб.`); + await ctx.editMessageText(`Вы успешно продали ${currentResources} ед. ${resourceType} за ${totalPrice} руб.`); +}); + +// Продажа ресурсов со склада +bot.command('sellstorage', async (ctx) => { + const user = await UserModel.findByPk(ctx.from.id); + const [resourceType, amountToSell] = ctx.message.text.split(' ').slice(1); + + if (!resourceType || !amountToSell) { + return await ctx.reply('Неверный формат команды. Пример: /sellstorage <тип_ресурса> <количество>'); + } + + const storage = await WarehouseModel.findOne({ + where: { playerId: user.telegram_id } + }); + + if (!storage || !storage[resourceType]) { + return await ctx.reply(`У вас нет ресурсов типа ${resourceType} на складе.`); + } + + const amount = parseInt(amountToSell, 10); + + if (isNaN(amount) || amount <= 0) { + return await ctx.reply('Укажите корректное количество для продажи.'); + } + + if (storage[resourceType] < amount) { + return await ctx.reply(`На складе недостаточно ресурсов типа ${resourceType}. Доступно: ${storage[resourceType]} единиц.`); + } + + const resourcePrice = await ResourcePriceModel.findOne({ where: { resource: resourceType } }); + + if (!resourcePrice) { + return await ctx.reply('Не удалось получить цену ресурса.'); + } + + const totalSale = Math.floor(amount * resourcePrice.price); + + // Обновляем данные + storage[resourceType] -= amount; + await storage.save(); + + user.money += totalSale; + await user.save(); + + // Ослабленная инфляция + resourcePrice.price = Math.round( + resourcePrice.price * Math.exp(-resourcePrice.fluctuationRate * (amount / 10)) // Дробное уменьшение инфляции + ); + + // Гарантируем, что цена не упадет ниже 50% от базовой цены + resourcePrice.price = Math.max(resourcePrice.price, Math.round(resourcePrice.basePrice * 0.5)); + + await resourcePrice.save(); + + return await ctx.reply( + `Вы продали ${amount} ед. ${resourceType} со склада за ${totalSale} руб.\nТекущая цена за единицу: ${resourcePrice.price.toFixed(0)} руб.` + ); }); // Найм грузовика @@ -976,12 +1051,12 @@ bot.action(/hire_truck_(\d+)/, async (ctx) => { async function initializePrices() { const resources = [ - { resource: 'wood', price: 10000, basePrice: 10000, fluctuationRate: 0.1, recoveryRate: 0.01 }, - { resource: 'coal', price: 20000, basePrice: 20000, fluctuationRate: 0.1, recoveryRate: 0.01 }, - { resource: 'oil', price: 50000, basePrice: 50000, fluctuationRate: 0.1, recoveryRate: 0.01 }, - { resource: 'metall', price: 100000, basePrice: 100000, fluctuationRate: 0.1, recoveryRate: 0.01 }, - { resource: 'gold', price: 300000, basePrice: 300000, fluctuationRate: 0.1, recoveryRate: 0.01 }, - { resource: 'diamond', price: 500000, basePrice: 500000, fluctuationRate: 0.1, recoveryRate: 0.01 }, + { resource: 'wood', price: 1000, basePrice: 1000, fluctuationRate: 0.002, recoveryRate: 0.15 }, + { resource: 'coal', price: 2000, basePrice: 2000, fluctuationRate: 0.002, recoveryRate: 0.12 }, + { resource: 'oil', price: 5000, basePrice: 5000, fluctuationRate: 0.001, recoveryRate: 0.1 }, + { resource: 'metall', price: 5000, basePrice: 5000, fluctuationRate: 0.001, recoveryRate: 0.1 }, + { resource: 'gold', price: 10000, basePrice: 10000, fluctuationRate: 0.0005, recoveryRate: 0.08 }, + { resource: 'diamond', price: 25000, basePrice: 25000, fluctuationRate: 0.0004, recoveryRate: 0.05 }, ]; for (const resource of resources) { @@ -994,19 +1069,6 @@ async function initializePrices() { initializePrices(); -setInterval(async () => { - const resources = await ResourcePriceModel.findAll() - for (let resource of resources) { - if (resource.price < resource.basePrice) { - resource.price += resource.recoveryRate - if (resource.price > resource.basePrice) { - resource.price = resource.basePrice - } - await resource.save() - } - } -}, 60000) // Обновляем цены каждые 60 секунд - // Функция добычи ресурсов const resourceProduction = async () => { try {