forked from zovos/bot_tg
- economy_background_tasks() была вставлена в середину main(), из-за чего dp.startup.register и asyncio.run(dp.start_polling) оказались мёртвым кодом внутри while True — бот никогда не поднимался - двойной fetchone() в get_user_stats (тот же баг что в PR #34, но в другом месте) - conn.close() вызывался до запросов за активностью, потом ещё раз — ProgrammingError - handle_central_bank_cmd строил текст но не делал await message.answer() Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
633 lines
26 KiB
Python
633 lines
26 KiB
Python
import sqlite3
|
||
import json
|
||
import logging
|
||
import os
|
||
from datetime import datetime, timedelta
|
||
from pathlib import Path
|
||
from typing import Dict, List, Optional, Tuple
|
||
import requests
|
||
|
||
logger = logging.getLogger(__name__)
|
||
|
||
# Пути к базам данных
|
||
ECONOMY_DB_PATH = os.getenv("ECONOMY_DB_PATH", "/db/economy.sqlite3")
|
||
|
||
class EconomyManager:
|
||
def __init__(self):
|
||
self.init_db()
|
||
|
||
def init_db(self):
|
||
"""Инициализация базы данных экономики"""
|
||
conn = sqlite3.connect(ECONOMY_DB_PATH)
|
||
cursor = conn.cursor()
|
||
|
||
# Таблица балансов пользователей
|
||
cursor.execute('''
|
||
CREATE TABLE IF NOT EXISTS user_balances (
|
||
user_id INTEGER PRIMARY KEY,
|
||
balance REAL DEFAULT 0.0,
|
||
daily_income REAL DEFAULT 0.0,
|
||
last_daily_reset DATE,
|
||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||
)
|
||
''')
|
||
|
||
# Таблица вкладов
|
||
cursor.execute('''
|
||
CREATE TABLE IF NOT EXISTS deposits (
|
||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||
user_id INTEGER,
|
||
amount REAL,
|
||
interest_rate REAL,
|
||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||
matures_at TIMESTAMP,
|
||
is_active BOOLEAN DEFAULT 1
|
||
)
|
||
''')
|
||
|
||
# Таблица кредитов
|
||
cursor.execute('''
|
||
CREATE TABLE IF NOT EXISTS loans (
|
||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||
user_id INTEGER,
|
||
amount REAL,
|
||
interest_rate REAL,
|
||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||
due_at TIMESTAMP,
|
||
is_repaid BOOLEAN DEFAULT 0
|
||
)
|
||
''')
|
||
|
||
# Таблица транзакций
|
||
cursor.execute('''
|
||
CREATE TABLE IF NOT EXISTS transactions (
|
||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||
from_user_id INTEGER,
|
||
to_user_id INTEGER,
|
||
amount REAL,
|
||
transaction_type TEXT,
|
||
description TEXT,
|
||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||
)
|
||
''')
|
||
|
||
# Таблица налогов
|
||
cursor.execute('''
|
||
CREATE TABLE IF NOT EXISTS taxes (
|
||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||
user_id INTEGER,
|
||
amount REAL,
|
||
tax_date DATE,
|
||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||
)
|
||
''')
|
||
|
||
# Таблица глобальных настроек экономики
|
||
cursor.execute('''
|
||
CREATE TABLE IF NOT EXISTS economy_settings (
|
||
key TEXT PRIMARY KEY,
|
||
value TEXT,
|
||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||
)
|
||
''')
|
||
|
||
# Таблица ежедневной активности пользователей
|
||
cursor.execute('''
|
||
CREATE TABLE IF NOT EXISTS daily_activity (
|
||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||
user_id INTEGER,
|
||
activity_date DATE,
|
||
message_count INTEGER DEFAULT 0,
|
||
last_activity_time TIMESTAMP,
|
||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||
UNIQUE(user_id, activity_date)
|
||
)
|
||
''')
|
||
|
||
# Таблица Центрального Банка
|
||
cursor.execute('''
|
||
CREATE TABLE IF NOT EXISTS central_bank (
|
||
id INTEGER PRIMARY KEY DEFAULT 1,
|
||
capital REAL DEFAULT 1000.0,
|
||
total_taxes_collected REAL DEFAULT 0.0,
|
||
total_inflation_adjustments REAL DEFAULT 0.0,
|
||
total_emissions REAL DEFAULT 0.0,
|
||
last_updated TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||
UNIQUE(id)
|
||
)
|
||
''')
|
||
|
||
# Вставка настроек по умолчанию
|
||
default_settings = {
|
||
'central_bank_rate': '7.5', # Ставка ЦБ РФ
|
||
'deposit_min_amount': '10.0',
|
||
'deposit_min_days': '7',
|
||
'loan_max_amount': '100.0',
|
||
'loan_interest_rate': '15.0',
|
||
'tax_rate': '13.0',
|
||
'transfer_limit_percent': '20.0',
|
||
'inflation_rate': '5.0',
|
||
'vanomasa_cooldown': '30', # дней между ваномаса
|
||
'message_reward_rate': '0.01', # см за сообщение
|
||
'last_activity_payout': '' # дата последней выплаты за активность
|
||
}
|
||
|
||
for key, value in default_settings.items():
|
||
cursor.execute('INSERT OR IGNORE INTO economy_settings (key, value) VALUES (?, ?)', (key, value))
|
||
|
||
# Инициализация Центрального Банка
|
||
cursor.execute('INSERT OR IGNORE INTO central_bank (id, capital) VALUES (1, 1000.0)')
|
||
|
||
conn.commit()
|
||
conn.close()
|
||
|
||
def get_user_balance(self, user_id: int) -> float:
|
||
"""Получить баланс пользователя"""
|
||
conn = sqlite3.connect(ECONOMY_DB_PATH)
|
||
cursor = conn.cursor()
|
||
cursor.execute('SELECT balance FROM user_balances WHERE user_id = ?', (user_id,))
|
||
result = cursor.fetchone()
|
||
conn.close()
|
||
return result[0] if result else 0.0
|
||
|
||
def update_balance(self, user_id: int, amount: float, transaction_type: str, description: str = ""):
|
||
"""Обновить баланс пользователя"""
|
||
conn = sqlite3.connect(ECONOMY_DB_PATH)
|
||
cursor = conn.cursor()
|
||
|
||
# Вставляем или обновляем баланс
|
||
cursor.execute('''
|
||
INSERT INTO user_balances (user_id, balance, daily_income, last_daily_reset)
|
||
VALUES (?, ?, 0.0, date('now'))
|
||
ON CONFLICT(user_id) DO UPDATE SET balance = balance + ?
|
||
''', (user_id, amount, amount))
|
||
|
||
# Записываем транзакцию
|
||
cursor.execute('''
|
||
INSERT INTO transactions (from_user_id, to_user_id, amount, transaction_type, description)
|
||
VALUES (?, ?, ?, ?, ?)
|
||
''', (user_id, user_id, amount, transaction_type, description))
|
||
|
||
conn.commit()
|
||
conn.close()
|
||
|
||
logger.info(f"Balance updated for user {user_id}: +{amount} ({transaction_type})")
|
||
|
||
def transfer_money(self, from_user_id: int, to_user_id: int, amount: float, description: str = "") -> bool:
|
||
"""Перевод денег между пользователями"""
|
||
if amount <= 0:
|
||
return False
|
||
|
||
from_balance = self.get_user_balance(from_user_id)
|
||
transfer_limit = from_balance * 0.2 # 20% от капитала
|
||
|
||
if amount > transfer_limit:
|
||
return False
|
||
|
||
if from_balance < amount:
|
||
return False
|
||
|
||
conn = sqlite3.connect(ECONOMY_DB_PATH)
|
||
cursor = conn.cursor()
|
||
|
||
# Обновляем балансы
|
||
cursor.execute('''
|
||
UPDATE user_balances SET balance = balance - ? WHERE user_id = ?
|
||
''', (amount, from_user_id))
|
||
|
||
cursor.execute('''
|
||
INSERT INTO user_balances (user_id, balance, daily_income, last_daily_reset)
|
||
VALUES (?, ?, 0.0, date('now'))
|
||
ON CONFLICT(user_id) DO UPDATE SET balance = balance + ?
|
||
''', (to_user_id, amount, amount))
|
||
|
||
# Записываем транзакцию
|
||
cursor.execute('''
|
||
INSERT INTO transactions (from_user_id, to_user_id, amount, transaction_type, description)
|
||
VALUES (?, ?, ?, ?, ?)
|
||
''', (from_user_id, to_user_id, amount, 'transfer', description))
|
||
|
||
conn.commit()
|
||
conn.close()
|
||
|
||
logger.info(f"Transfer: {amount} from user {from_user_id} to user {to_user_id}")
|
||
return True
|
||
|
||
def create_deposit(self, user_id: int, amount: float, days: int) -> bool:
|
||
"""Создать вклад"""
|
||
if amount <= 0:
|
||
return False
|
||
|
||
balance = self.get_user_balance(user_id)
|
||
min_deposit = float(self.get_setting('deposit_min_amount'))
|
||
|
||
if amount < min_deposit:
|
||
return False
|
||
|
||
if balance < amount:
|
||
return False
|
||
|
||
central_bank_rate = float(self.get_setting('central_bank_rate'))
|
||
matures_at = datetime.now() + timedelta(days=days)
|
||
|
||
conn = sqlite3.connect(ECONOMY_DB_PATH)
|
||
cursor = conn.cursor()
|
||
|
||
# Списываем деньги со счета
|
||
cursor.execute('UPDATE user_balances SET balance = balance - ? WHERE user_id = ?', (amount, user_id))
|
||
|
||
# Создаем вклад
|
||
cursor.execute('''
|
||
INSERT INTO deposits (user_id, amount, interest_rate, matures_at)
|
||
VALUES (?, ?, ?, ?)
|
||
''', (user_id, amount, central_bank_rate, matures_at))
|
||
|
||
conn.commit()
|
||
conn.close()
|
||
|
||
logger.info(f"Deposit created: user {user_id}, amount {amount}, rate {central_bank_rate}%")
|
||
return True
|
||
|
||
def create_loan(self, user_id: int, amount: float, days: int) -> bool:
|
||
"""Создать кредит"""
|
||
if amount <= 0:
|
||
return False
|
||
|
||
max_loan = float(self.get_setting('loan_max_amount'))
|
||
loan_rate = float(self.get_setting('loan_interest_rate'))
|
||
|
||
if amount > max_loan:
|
||
return False
|
||
|
||
due_at = datetime.now() + timedelta(days=days)
|
||
|
||
conn = sqlite3.connect(ECONOMY_DB_PATH)
|
||
cursor = conn.cursor()
|
||
|
||
# Начисляем деньги на счет
|
||
cursor.execute('''
|
||
INSERT INTO user_balances (user_id, balance, daily_income, last_daily_reset)
|
||
VALUES (?, ?, 0.0, date('now'))
|
||
ON CONFLICT(user_id) DO UPDATE SET balance = balance + ?
|
||
''', (user_id, amount, amount))
|
||
|
||
# Создаем кредит
|
||
cursor.execute('''
|
||
INSERT INTO loans (user_id, amount, interest_rate, due_at)
|
||
VALUES (?, ?, ?, ?)
|
||
''', (user_id, amount, loan_rate, due_at))
|
||
|
||
conn.commit()
|
||
conn.close()
|
||
|
||
logger.info(f"Loan created: user {user_id}, amount {amount}, rate {loan_rate}%")
|
||
return True
|
||
|
||
def repay_loan(self, user_id: int, loan_id: int) -> bool:
|
||
"""Погасить кредит"""
|
||
conn = sqlite3.connect(ECONOMY_DB_PATH)
|
||
cursor = conn.cursor()
|
||
|
||
cursor.execute('SELECT amount, interest_rate, is_repaid FROM loans WHERE id = ? AND user_id = ?', (loan_id, user_id))
|
||
loan = cursor.fetchone()
|
||
|
||
if not loan or loan[2]: # Кредит не найден или уже погашен
|
||
conn.close()
|
||
return False
|
||
|
||
amount, rate, _ = loan
|
||
total_repayment = amount * (1 + rate / 100)
|
||
|
||
balance = self.get_user_balance(user_id)
|
||
if balance < total_repayment:
|
||
conn.close()
|
||
return False
|
||
|
||
# Списываем деньги
|
||
cursor.execute('UPDATE user_balances SET balance = balance - ? WHERE user_id = ?', (total_repayment, user_id))
|
||
|
||
# Отмечаем кредит как погашенный
|
||
cursor.execute('UPDATE loans SET is_repaid = 1 WHERE id = ?', (loan_id,))
|
||
|
||
conn.commit()
|
||
conn.close()
|
||
|
||
logger.info(f"Loan repaid: user {user_id}, loan {loan_id}, amount {total_repayment}")
|
||
return True
|
||
|
||
def collect_daily_taxes(self):
|
||
"""Сбор ежедневных налогов"""
|
||
tax_rate = float(self.get_setting('tax_rate')) / 100
|
||
conn = sqlite3.connect(ECONOMY_DB_PATH)
|
||
cursor = conn.cursor()
|
||
|
||
# Получаем всех пользователей с ежедневным доходом
|
||
cursor.execute('''
|
||
SELECT user_id, daily_income FROM user_balances
|
||
WHERE daily_income > 0 AND (last_daily_reset != date('now') OR last_daily_reset IS NULL)
|
||
''')
|
||
|
||
users = cursor.fetchall()
|
||
|
||
total_taxes_collected = 0.0
|
||
|
||
for user_id, daily_income in users:
|
||
tax_amount = daily_income * tax_rate
|
||
if tax_amount > 0:
|
||
# Списываем налог
|
||
cursor.execute(
|
||
'UPDATE user_balances SET balance = balance - ?, daily_income = 0, last_daily_reset = date(\'now\') WHERE user_id = ?',
|
||
(tax_amount, user_id)
|
||
)
|
||
|
||
# Записываем налог
|
||
cursor.execute('INSERT INTO taxes (user_id, amount, tax_date) VALUES (?, ?, date("now"))', (user_id, tax_amount))
|
||
|
||
total_taxes_collected += tax_amount
|
||
|
||
# Переводим собранные налоги в Центральный Банк
|
||
if total_taxes_collected > 0:
|
||
cursor.execute('UPDATE central_bank SET capital = capital + ?, total_taxes_collected = total_taxes_collected + ? WHERE id = 1',
|
||
(total_taxes_collected, total_taxes_collected))
|
||
|
||
conn.commit()
|
||
conn.close()
|
||
|
||
logger.info(f"Daily taxes collected: {total_taxes_collected:.2f} cm from {len(users)} users")
|
||
|
||
def count_message(self, user_id: int):
|
||
"""Учесть сообщение пользователя"""
|
||
conn = sqlite3.connect(ECONOMY_DB_PATH)
|
||
cursor = conn.cursor()
|
||
|
||
today = datetime.now().strftime('%Y-%m-%d')
|
||
|
||
# Вставляем или обновляем счетчик сообщений за сегодня
|
||
cursor.execute('''
|
||
INSERT INTO daily_activity (user_id, activity_date, message_count, last_activity_time)
|
||
VALUES (?, ?, 1, CURRENT_TIMESTAMP)
|
||
ON CONFLICT(user_id, activity_date)
|
||
DO UPDATE SET
|
||
message_count = message_count + 1,
|
||
last_activity_time = CURRENT_TIMESTAMP
|
||
''', (user_id, today))
|
||
|
||
conn.commit()
|
||
conn.close()
|
||
|
||
def pay_daily_activity_rewards(self) -> int:
|
||
"""Начислить вознаграждения за ежедневную активность"""
|
||
reward_rate = float(self.get_setting('message_reward_rate'))
|
||
last_payout = self.get_setting('last_activity_payout')
|
||
today = datetime.now().strftime('%Y-%m-%d')
|
||
|
||
# Проверяем, не выплачивали ли уже сегодня
|
||
if last_payout == today:
|
||
return 0
|
||
|
||
conn = sqlite3.connect(ECONOMY_DB_PATH)
|
||
cursor = conn.cursor()
|
||
|
||
# Получаем всех пользователей с активностью за вчерашний день
|
||
yesterday = (datetime.now() - timedelta(days=1)).strftime('%Y-%m-%d')
|
||
cursor.execute('''
|
||
SELECT user_id, message_count FROM daily_activity
|
||
WHERE activity_date = ? AND message_count > 0
|
||
''', (yesterday,))
|
||
|
||
users = cursor.fetchall()
|
||
total_paid = 0
|
||
|
||
for user_id, message_count in users:
|
||
reward = message_count * reward_rate
|
||
if reward > 0:
|
||
# Обновляем баланс
|
||
cursor.execute('''
|
||
INSERT INTO user_balances (user_id, balance, daily_income, last_daily_reset)
|
||
VALUES (?, ?, 0.0, date('now'))
|
||
ON CONFLICT(user_id) DO UPDATE SET
|
||
balance = balance + ?,
|
||
daily_income = daily_income + ?
|
||
''', (user_id, reward, reward, reward))
|
||
|
||
# Записываем транзакцию
|
||
cursor.execute('''
|
||
INSERT INTO transactions (from_user_id, to_user_id, amount, transaction_type, description)
|
||
VALUES (?, ?, ?, ?, ?)
|
||
''', (user_id, user_id, reward, 'activity_reward', f'Вознаграждение за {message_count} сообщений'))
|
||
|
||
total_paid += reward
|
||
|
||
# Обновляем дату последней выплаты
|
||
cursor.execute('UPDATE economy_settings SET value = ? WHERE key = ?', (today, 'last_activity_payout'))
|
||
|
||
conn.commit()
|
||
conn.close()
|
||
|
||
logger.info(f"Activity rewards paid: {total_paid:.2f} cm to {len(users)} users")
|
||
return len(users)
|
||
|
||
def get_central_bank_stats(self) -> Dict:
|
||
"""Получить статистику Центрального Банка"""
|
||
conn = sqlite3.connect(ECONOMY_DB_PATH)
|
||
cursor = conn.cursor()
|
||
|
||
cursor.execute('SELECT capital, total_taxes_collected, total_inflation_adjustments, total_emissions FROM central_bank WHERE id = 1')
|
||
result = cursor.fetchone()
|
||
|
||
conn.close()
|
||
|
||
if result:
|
||
return {
|
||
'capital': result[0],
|
||
'total_taxes_collected': result[1],
|
||
'total_inflation_adjustments': result[2],
|
||
'total_emissions': result[3]
|
||
}
|
||
else:
|
||
return {
|
||
'capital': 1000.0,
|
||
'total_taxes_collected': 0.0,
|
||
'total_inflation_adjustments': 0.0,
|
||
'total_emissions': 0.0
|
||
}
|
||
|
||
def update_central_bank(self, capital_change: float, transaction_type: str, description: str = ""):
|
||
"""Обновить капитал Центрального Банка"""
|
||
conn = sqlite3.connect(ECONOMY_DB_PATH)
|
||
cursor = conn.cursor()
|
||
|
||
# Обновляем капитал
|
||
cursor.execute('''
|
||
UPDATE central_bank SET
|
||
capital = capital + ?,
|
||
last_updated = CURRENT_TIMESTAMP
|
||
WHERE id = 1
|
||
''', (capital_change,))
|
||
|
||
# Обновляем соответствующую статистику
|
||
if transaction_type == 'tax':
|
||
cursor.execute('UPDATE central_bank SET total_taxes_collected = total_taxes_collected + ? WHERE id = 1', (abs(capital_change),))
|
||
elif transaction_type == 'inflation':
|
||
cursor.execute('UPDATE central_bank SET total_inflation_adjustments = total_inflation_adjustments + ? WHERE id = 1', (abs(capital_change),))
|
||
elif transaction_type == 'emission':
|
||
cursor.execute('UPDATE central_bank SET total_emissions = total_emissions + ? WHERE id = 1', (abs(capital_change),))
|
||
|
||
conn.commit()
|
||
conn.close()
|
||
|
||
logger.info(f"Central bank updated: {capital_change} ({transaction_type})")
|
||
|
||
def emit_money(self, amount: float, reason: str = "") -> bool:
|
||
"""Эмиссия денег - добавление денег в систему из ЦБ"""
|
||
cb_stats = self.get_central_bank_stats()
|
||
|
||
if cb_stats['capital'] < amount:
|
||
return False
|
||
|
||
# Уменьшаем капитал ЦБ
|
||
self.update_central_bank(-amount, 'emission', reason)
|
||
|
||
# Здесь можно добавить логику распределения денег
|
||
# Например, пропорционально текущим балансам или равными долями
|
||
|
||
logger.info(f"Money emitted: {amount} cm ({reason})")
|
||
return True
|
||
|
||
def vanomasa(self) -> bool:
|
||
"""Полное обнуление всех балансов"""
|
||
conn = sqlite3.connect(ECONOMY_DB_PATH)
|
||
cursor = conn.cursor()
|
||
|
||
# Проверяем кулдаун
|
||
cursor.execute('SELECT value FROM economy_settings WHERE key = "last_vanomasa"')
|
||
last_vanomasa = cursor.fetchone()
|
||
|
||
if last_vanomasa:
|
||
last_date = datetime.strptime(last_vanomasa[0], '%Y-%m-%d')
|
||
cooldown_days = int(self.get_setting('vanomasa_cooldown'))
|
||
if datetime.now() - last_date < timedelta(days=cooldown_days):
|
||
conn.close()
|
||
return False
|
||
|
||
# Обнуляем все балансы
|
||
cursor.execute('UPDATE user_balances SET balance = 0, daily_income = 0')
|
||
|
||
# Записываем дату ваномаса
|
||
cursor.execute('INSERT OR REPLACE INTO economy_settings (key, value, updated_at) VALUES ("last_vanomasa", date("now"), CURRENT_TIMESTAMP)')
|
||
|
||
conn.commit()
|
||
conn.close()
|
||
|
||
logger.warning("VANOMASA: All balances reset to zero!")
|
||
return True
|
||
|
||
def get_setting(self, key: str) -> str:
|
||
"""Получить настройку экономики"""
|
||
conn = sqlite3.connect(ECONOMY_DB_PATH)
|
||
cursor = conn.cursor()
|
||
cursor.execute('SELECT value FROM economy_settings WHERE key = ?', (key,))
|
||
result = cursor.fetchone()
|
||
conn.close()
|
||
return result[0] if result else '0'
|
||
|
||
def update_setting(self, key: str, value: str):
|
||
"""Обновить настройку экономики"""
|
||
conn = sqlite3.connect(ECONOMY_DB_PATH)
|
||
cursor = conn.cursor()
|
||
cursor.execute('INSERT OR REPLACE INTO economy_settings (key, value, updated_at) VALUES (?, ?, CURRENT_TIMESTAMP)', (key, value))
|
||
conn.commit()
|
||
conn.close()
|
||
|
||
def get_user_stats(self, user_id: int) -> Dict:
|
||
"""Получить статистику пользователя"""
|
||
conn = sqlite3.connect(ECONOMY_DB_PATH)
|
||
cursor = conn.cursor()
|
||
|
||
# Баланс
|
||
cursor.execute('SELECT balance FROM user_balances WHERE user_id = ?', (user_id,))
|
||
row = cursor.fetchone()
|
||
balance = row[0] if row else 0.0
|
||
|
||
# Активные вклады
|
||
cursor.execute('SELECT COUNT(*), SUM(amount) FROM deposits WHERE user_id = ? AND is_active = 1', (user_id,))
|
||
deposits = cursor.fetchone()
|
||
|
||
# Активные кредиты
|
||
cursor.execute('SELECT COUNT(*), SUM(amount) FROM loans WHERE user_id = ? AND is_repaid = 0', (user_id,))
|
||
loans = cursor.fetchone()
|
||
|
||
# Получаем статистику сообщений за сегодня
|
||
today = datetime.now().strftime('%Y-%m-%d')
|
||
cursor.execute('SELECT message_count FROM daily_activity WHERE user_id = ? AND activity_date = ?', (user_id, today))
|
||
today_messages = cursor.fetchone()
|
||
|
||
# Получаем статистику сообщений за вчера
|
||
yesterday = (datetime.now() - timedelta(days=1)).strftime('%Y-%m-%d')
|
||
cursor.execute('SELECT message_count FROM daily_activity WHERE user_id = ? AND activity_date = ?', (user_id, yesterday))
|
||
yesterday_messages = cursor.fetchone()
|
||
|
||
conn.close()
|
||
|
||
return {
|
||
'balance': balance,
|
||
'active_deposits_count': deposits[0] or 0,
|
||
'active_deposits_sum': deposits[1] or 0.0,
|
||
'active_loans_count': loans[0] or 0,
|
||
'active_loans_sum': loans[1] or 0.0,
|
||
'today_messages': today_messages[0] if today_messages else 0,
|
||
'yesterday_messages': yesterday_messages[0] if yesterday_messages else 0
|
||
}
|
||
|
||
def regulate_inflation(self):
|
||
"""Регулирование инфляции через Центральный Банк"""
|
||
inflation_rate = float(self.get_setting('inflation_rate'))
|
||
total_supply = 0.0
|
||
user_count = 0
|
||
|
||
conn = sqlite3.connect(ECONOMY_DB_PATH)
|
||
cursor = conn.cursor()
|
||
|
||
# Получаем общую массу денег и количество пользователей
|
||
cursor.execute('SELECT SUM(balance), COUNT(*) FROM user_balances')
|
||
result = cursor.fetchone()
|
||
if result[0]:
|
||
total_supply = result[0]
|
||
user_count = result[1]
|
||
|
||
# Получаем статистику ЦБ
|
||
cursor.execute('SELECT capital FROM central_bank WHERE id = 1')
|
||
cb_result = cursor.fetchone()
|
||
cb_capital = cb_result[0] if cb_result else 1000.0
|
||
|
||
conn.close()
|
||
|
||
# Если инфляция высокая, ЦБ может скупать деньги с рынка
|
||
if inflation_rate > 10.0 and total_supply > 1000 and cb_capital > 100:
|
||
# ЦБ скупает деньги для борьбы с инфляцией
|
||
buyback_amount = min(total_supply * 0.05, cb_capital * 0.1) # 5% от массы или 10% от капитала ЦБ
|
||
|
||
# Уменьшаем капитал ЦБ (скупка денег)
|
||
self.update_central_bank(-buyback_amount, 'inflation', f'Anti-inflation measures: buying back {buyback_amount:.2f} cm')
|
||
|
||
# Увеличиваем налоги для дополнительной борьбы с инфляцией
|
||
new_tax_rate = min(20.0, 13.0 + (inflation_rate - 10.0) * 0.5)
|
||
self.update_setting('tax_rate', str(new_tax_rate))
|
||
|
||
logger.info(f"Inflation regulation: CB bought back {buyback_amount:.2f} cm, tax rate increased to {new_tax_rate}%")
|
||
|
||
# Если дефляция (низкая инфляция) и много денег в ЦБ, можно делать эмиссию
|
||
elif inflation_rate < 2.0 and total_supply < 500 and cb_capital > 200:
|
||
emission_amount = cb_capital * 0.05 # 5% от капитала ЦБ
|
||
|
||
# Эмиссия денег через ЦБ
|
||
self.update_central_bank(-emission_amount, 'emission', f'Economic stimulus: emitting {emission_amount:.2f} cm')
|
||
|
||
# Уменьшаем налоги для стимуляции экономики
|
||
new_tax_rate = max(10.0, 13.0 - (2.0 - inflation_rate) * 1.5)
|
||
self.update_setting('tax_rate', str(new_tax_rate))
|
||
|
||
logger.info(f"Economic stimulus: CB emitted {emission_amount:.2f} cm, tax rate decreased to {new_tax_rate}%")
|
||
|
||
# Глобальный экземпляр
|
||
economy = EconomyManager()
|