from datetime import datetime from app.db.database import users_collection, sessions_collection from fastapi import HTTPException class CoinsService: async def update_player_coins(self, player_id: str, player_name: str, online_time: int, server_ip: str): """Обновляет монеты игрока на основе времени онлайн""" # Находим пользователя user = await self._find_user_by_uuid(player_id) if not user: return # Пользователь не найден # Находим последнее обновление монет last_update = await sessions_collection.find_one({ "player_id": player_id, "server_ip": server_ip, "update_type": "coins_update" }, sort=[("timestamp", -1)]) now = datetime.now() current_coins = user.get("coins", 0) current_total_time = user.get("total_time_played", 0) if last_update: # Время с последнего начисления last_timestamp = last_update["timestamp"] seconds_since_update = int((now - last_timestamp).total_seconds()) # Начисляем монеты только за полные минуты minutes_to_reward = seconds_since_update // 60 # Если прошло меньше минуты, пропускаем if minutes_to_reward < 1: return else: # Первое обновление (ограничиваем для безопасности) minutes_to_reward = min(online_time // 60, 5) if minutes_to_reward > 0: # Обновляем монеты и время new_coins = current_coins + minutes_to_reward new_total_time = current_total_time + (minutes_to_reward * 60) # Сохраняем в БД await users_collection.update_one( {"_id": user["_id"]}, {"$set": { "coins": new_coins, "total_time_played": new_total_time }} ) # Сохраняем запись о начислении await sessions_collection.insert_one({ "player_id": player_id, "player_name": player_name, "server_ip": server_ip, "update_type": "coins_update", "timestamp": now, "minutes_added": minutes_to_reward, "coins_added": minutes_to_reward }) print(f"[{now}] Игроку {user.get('username')} начислено {minutes_to_reward} монет. " f"Всего монет: {new_coins}") async def _find_user_by_uuid(self, player_id: str): """Находит пользователя по UUID с поддержкой разных форматов""" # Пробуем найти как есть user = await users_collection.find_one({"uuid": player_id}) if user: return user # Пробуем разные форматы UUID if '-' in player_id: user = await users_collection.find_one({"uuid": player_id.replace('-', '')}) else: formatted_uuid = f"{player_id[:8]}-{player_id[8:12]}-{player_id[12:16]}-{player_id[16:20]}-{player_id[20:]}" user = await users_collection.find_one({"uuid": formatted_uuid}) return user async def get_player_coins(self, username: str): """Возвращает информацию о монетах и времени игрока""" user = await users_collection.find_one({"username": username}) if not user: return None total_time = user.get("total_time_played", 0) hours, remainder = divmod(total_time, 3600) minutes, seconds = divmod(remainder, 60) return { "username": username, "coins": user.get("coins", 0), "total_time_played": { "seconds": total_time, "formatted": f"{hours}ч {minutes}м {seconds}с" } } async def get_balance(self, username: str) -> int: """Получить текущий баланс пользователя""" user = await users_collection.find_one({"username": username}) if not user: raise HTTPException(status_code=404, detail=f"Пользователь {username} не найден") return user.get("coins", 0) async def increase_balance(self, username: str, amount: int) -> int: """Увеличить баланс пользователя""" if amount <= 0: raise ValueError("Сумма должна быть положительной") result = await users_collection.update_one( {"username": username}, {"$inc": {"coins": amount}} ) if result.modified_count == 0: raise HTTPException(status_code=404, detail=f"Пользователь {username} не найден") user = await users_collection.find_one({"username": username}) return user.get("coins", 0) async def decrease_balance(self, username: str, amount: int) -> int: """Уменьшить баланс пользователя""" if amount <= 0: raise ValueError("Сумма должна быть положительной") result = await users_collection.update_one( {"username": username}, {"$inc": {"coins": -amount}} # Уменьшаем на отрицательное значение ) if result.modified_count == 0: raise HTTPException(status_code=404, detail=f"Пользователь {username} не найден") user = await users_collection.find_one({"username": username}) return user.get("coins", 0)