From bf04318a1f35d0a98b5dedb38890555a82ff54cd Mon Sep 17 00:00:00 2001 From: Degradin <42292046+Degradin@users.noreply.github.com> Date: Sun, 22 Dec 2024 19:11:20 +0300 Subject: [PATCH] v0.0.3 --- bot.js | 272 +++++++++++++++++++++++++++------- config/index.js | 1 + models/enterprise.model.js | 4 + models/resourceprice.model.js | 4 +- 4 files changed, 226 insertions(+), 55 deletions(-) diff --git a/bot.js b/bot.js index eade78b..fdbdf04 100644 --- a/bot.js +++ b/bot.js @@ -19,6 +19,7 @@ const { EnterpriseModel, WarehouseModel, SaleModel, + ResourcePriceModel, SkillsModel, } = global.config const bot = new Telegraf(process.env.BOT_TOKEN) @@ -392,52 +393,76 @@ function getEnterpriseEmoji(resourceType) { return emojis[resourceType] || '🏭' } -// Построение предприятия -bot.action('build_enterprise', async (ctx) => { +bot.action('my_enterprises', async (ctx) => { const user = await UserModel.findByPk(ctx.from.id); const enterprises = await EnterpriseModel.findAll({ where: { playerId: user.telegram_id } }); - if (enterprises.length >= 5) { - return await ctx.reply('Вы достигли максимального числа предприятий.'); + if (enterprises.length === 0) { + return await ctx.reply('У вас нет предприятий.'); } - const resourcePrices = { - wood: 10000, - coal: 20000, - oil: 50000, - metall: 100000, - gold: 300000, - diamond: 500000 - }; + let message = `🏭 Мои предприятия:\n\n`; + const buttons = []; - let message = `🛠️ Постройка предприятия:\n`; - for (const [resource, price] of Object.entries(resourcePrices)) { - const resourceName = getResourceName(resource); - message += `${resourceName}: ${price} монет\n`; - } - message += '\nВыберите тип предприятия:'; + enterprises.forEach((enterprise) => { + message += `🔹 ${enterprise.name} (Уровень: ${enterprise.level}, Эффективность: ${enterprise.efficiency} ед/ч)\n`; + buttons.push([ + { text: `📈 Улучшить ${enterprise.name}`, callback_data: `upgrade_${enterprise.id}` }, + { text: `🚛 Управлять ${enterprise.name}`, callback_data: `manage_${enterprise.id}` } + ]); + }); - const buttons = [ - [ - { text: '🌲', callback_data: 'build_wood' }, - { text: '⛏️', callback_data: 'build_coal' } - ], - [ - { text: '🛢️', callback_data: 'build_oil' }, - { text: '⚙️', callback_data: 'build_metall' } - ], - [ - { text: '🥇', callback_data: 'build_gold' }, - { text: '💎', callback_data: 'build_diamond' } - ] - ]; + buttons.push([{ text: '⬅️ Назад', callback_data: 'back_to_menu' }]); return await ctx.reply(message, Markup.inlineKeyboard(buttons).resize()); }); +// Построение предприятия +bot.action('build_enterprise', async (ctx) => { + try { + const user = await UserModel.findByPk(ctx.from.id); + if (!user) { + return await ctx.reply('Пользователь не найден.'); + } + + const enterprises = await EnterpriseModel.findAll({ + where: { playerId: user.telegram_id } + }); + + if (enterprises.length >= 5) { + return await ctx.reply('Вы достигли максимального числа предприятий.'); + } + + // Получаем текущие цены из базы данных + const resourcePrices = await ResourcePriceModel.findAll(); + if (!resourcePrices || resourcePrices.length === 0) { + return await ctx.reply('Цены на ресурсы отсутствуют. Пожалуйста, попробуйте позже.'); + } + + let message = `🛠️ Постройка предприятия:\n`; + const buttons = []; + + for (const resource of resourcePrices) { + const resourceName = getEnterpriseEmoji(resource.resource); + message += `${resourceName}: ${Math.round(resource.price)} монет\n`; + + // Генерируем кнопки для каждого ресурса + buttons.push([ + { text: resourceName, callback_data: `build_${resource.resource}` } + ]); + } + + message += '\nВыберите тип предприятия:'; + return await ctx.reply(message, Markup.inlineKeyboard(buttons).resize()); + } catch (error) { + console.error('Ошибка в build_enterprise:', error); + return await ctx.reply('Произошла ошибка при обработке запроса. Попробуйте снова.'); + } +}); + // Построение предприятия по выбранному типу bot.action(/build_(wood|coal|oil|metall|gold|diamond)/, async (ctx) => { let user = await UserModel.findByPk(ctx.from.id) @@ -752,42 +777,183 @@ bot.action('hire_truck', async (ctx) => { return await ctx.reply(`Вы наняли грузовик для транспортировки ресурсов!`) }) -async function initializeResourcePrices() { +async function initializePrices() { const resources = [ - { resourceType: 'wood', basePrice: 100, recoveryRate: 1 }, - { resourceType: 'coal', basePrice: 200, recoveryRate: 2 }, - { resourceType: 'oil', basePrice: 500, recoveryRate: 5 }, - { resourceType: 'metall', basePrice: 1000, recoveryRate: 10 }, - { resourceType: 'gold', basePrice: 3000, recoveryRate: 15 }, - { resourceType: 'diamond', basePrice: 5000, recoveryRate: 20 } - ] + { 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 }, + ]; - for (let resource of resources) { + for (const resource of resources) { await ResourcePriceModel.findOrCreate({ - where: { resourceType: resource.resourceType }, - defaults: { - currentPrice: resource.basePrice, - basePrice: resource.basePrice, - recoveryRate: resource.recoveryRate - } - }) + where: { resource: resource.resource }, + defaults: resource, + }); } } -initializeResourcePrices() + +initializePrices(); setInterval(async () => { const resources = await ResourcePriceModel.findAll() for (let resource of resources) { - if (resource.currentPrice < resource.basePrice) { - resource.currentPrice += resource.recoveryRate - if (resource.currentPrice > resource.basePrice) { - resource.currentPrice = resource.basePrice + 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 { + // Получаем все предприятия без фильтрации по пользователю + const enterprises = await EnterpriseModel.findAll(); + + for (const enterprise of enterprises) { + const { id, efficiency, warehouseCapacity, resourceType, playerId, level, currentResources } = enterprise; + + // Рассчитываем добычу ресурсов + const producedResources = efficiency * level; + + // Проверяем, не превышает ли общая сумма ресурсов ёмкость склада + if (currentResources + producedResources <= warehouseCapacity) { + enterprise.currentResources = currentResources + producedResources; + await enterprise.save(); + console.log(`Предприятие ${id}: добыто ${producedResources} единиц ${resourceType}.`); + } else { + console.log(`Предприятие ${id}: склад заполнен.`); + } + + // Получаем универсальный склад, если он есть + const Warehouse = await WarehouseModel.findOne({ + where: { playerId: playerId } // Привязка к игроку через playerId + }); + + if (Warehouse) { + const transportableAmount = Math.min( + enterprise.currentResources, + universalWarehouse.remainingCapacity + ); + + if (transportableAmount > 0) { + // Перемещаем ресурсы + enterprise.currentResources -= transportableAmount; + Warehouse.resources[resourceType] = + (Warehouse.resources[resourceType] || 0) + transportableAmount; + + await enterprise.save(); + await Warehouse.save(); + + console.log(`Предприятие ${id}: перевезено ${transportableAmount} единиц ${resourceType} на универсальный склад.`); + } else { + console.log(`Универсальный склад игрока ${playerId} заполнен.`); + } + } + } + } catch (error) { + console.error('Ошибка добычи ресурсов:', error); + } +}; + + +// Запуск функции каждый час +setInterval(resourceProduction, 60 * 60 * 1000); + +// Функция добычи ресурсов +const resourceTransportation = async () => { + try { + const enterprises = await EnterpriseModel.findAll(); + + for (const enterprise of enterprises) { + const { id, resourceType, currentResources, playerId } = enterprise; + + if (currentResources > 0) { + // Получаем склад игрока + const warehouse = await WarehouseModel.findOne({ + where: { playerId } + }); + + if (!warehouse) { + console.log(`У игрока ${playerId} нет склада.`); + continue; + } + + // Получаем грузовики, привязанные к этому складу + const trucks = await Truck.findAll({ + where: { warehouseId: warehouse.id } + }); + + if (trucks.length === 0) { + console.log(`На складе ${warehouse.id} нет доступных грузовиков.`); + continue; + } + + // Транспортируем ресурсы + let totalTransported = 0; + for (const truck of trucks) { + const transportableAmount = Math.min( + truck.capacity, // Максимальная вместимость грузовика + currentResources, // Доступные ресурсы на предприятии + warehouse.capacity - getWarehouseUsedCapacity(warehouse) // Свободное место на складе + ); + + if (transportableAmount > 0) { + // Обновляем данные склада + warehouse[resourceType] = (warehouse[resourceType] || 0) + transportableAmount; + + // Уменьшаем ресурсы на предприятии + enterprise.currentResources -= transportableAmount; + + await warehouse.save(); + await enterprise.save(); + + totalTransported += transportableAmount; + + console.log(`Грузовик ${truck.id} перевёз ${transportableAmount} единиц ${resourceType}.`); + } + + // Прекращаем, если на предприятии закончились ресурсы + if (enterprise.currentResources === 0) break; + } + + if (totalTransported === 0) { + console.log(`Склад ${warehouse.id} заполнен. Ресурсы не перевезены.`); + } + } else { + console.log(`Предприятие ${id} не имеет доступных ресурсов для транспортировки.`); + } + } + } catch (error) { + console.error('Ошибка транспортировки ресурсов:', error); + } +}; + +// Расчёт используемой ёмкости склада +const getWarehouseUsedCapacity = (warehouse) => { + const resources = ['wood', 'coal', 'oil', 'metall', 'gold', 'diamond']; + return resources.reduce((sum, resource) => sum + (warehouse[resource] || 0), 0); +}; + +// Запускаем процесс транспортировки каждый час +setInterval(resourceTransportation, 60 * 60 * 1000); + + +bot.command('force_prod', async (ctx) => { + resourceProduction() + return await ctx.reply(`Принудительно добыто.`) +}) + +bot.command('force_transport', async (ctx) => { + resourceTransportation() + return await ctx.reply(`Принудительно перевезено.`) +}) + /////////////////////////////////////Enterprise Update end////////////////////////////////////////////////// /////////////////////////////////////Admin Commands////////////////////////////////////////////////// diff --git a/config/index.js b/config/index.js index d612781..8a1b13b 100644 --- a/config/index.js +++ b/config/index.js @@ -21,6 +21,7 @@ module.exports = { LobbyModel: require('../models/lobby.model'), EnterpriseModel: require('../models/enterprise.model'), WarehouseModel: require('../models/warehouse.model'), + ResourcePriceModel: require('../models/resourceprice.model'), SaleModel: require('../models/sales.model'), mainChat : -1001895132127, adminList : [275416286], diff --git a/models/enterprise.model.js b/models/enterprise.model.js index 897e99d..3f60421 100644 --- a/models/enterprise.model.js +++ b/models/enterprise.model.js @@ -22,6 +22,10 @@ const Enterprise = sequelize.define('enterprise', { type: Sequelize.INTEGER, // ёмкость склада (максимальное количество ресурса) defaultValue: 100 }, + currentResources: { + type: Sequelize.INTEGER, + defaultValue: 0 // Начальное количество ресурсов + }, playerId: { type: Sequelize.INTEGER, references: { diff --git a/models/resourceprice.model.js b/models/resourceprice.model.js index 9befed2..bad5128 100644 --- a/models/resourceprice.model.js +++ b/models/resourceprice.model.js @@ -1,7 +1,7 @@ const sequelize = require('../db'); const {DataTypes} = require('sequelize'); -const ResourcePriceModel = sequelize.define('resource_price', { +const ResourcePrice = sequelize.define('resource_price', { resource: { type: DataTypes.STRING, allowNull: false, @@ -29,4 +29,4 @@ const ResourcePriceModel = sequelize.define('resource_price', { }, }); -module.exports = ResourcePriceModel; +module.exports = ResourcePrice;