Skip to content

Commit

Permalink
Merge pull request #46 from HamletSargsyan/achievements
Browse files Browse the repository at this point in the history
Achievements
  • Loading branch information
HamletSargsyan authored Aug 16, 2024
2 parents 4ddf884 + 22cb383 commit 165feaf
Show file tree
Hide file tree
Showing 13 changed files with 379 additions and 6 deletions.
1 change: 1 addition & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"mypy.enabled": false,
"cSpell.language": "en,ru",
"cSpell.words": [
"ачивки",
"бабла",
"буст",
"бусте",
Expand Down
2 changes: 1 addition & 1 deletion pyrightconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,5 @@
"pythonVersion": "3.11",
"pythonPlatform": "Linux",
"reportMissingTypeStubs": false,
"reportOptionalMemberAccess": false
"reportOptionalMemberAccess": false,
}
52 changes: 52 additions & 0 deletions src/base/achievements.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
from typing import Final

from helpers.datatypes import Achievement


ACHIEVEMENTS: Final[list[Achievement]] = [
Achievement(
name="работяга",
emoji="💼",
desc="поработай 10 раз",
need=10,
reward={
"бабло": 10_000,
},
),
Achievement(
name="бродяга",
emoji="🚶",
desc="погуляй 10 раз",
need=10,
reward={
"бокс": 2,
},
),
Achievement(
name="сонный",
emoji="💤",
desc="поспи 15 раз",
need=15,
reward={
"энергос": 10,
},
),
Achievement(
name="игроман",
emoji="🎮",
desc="поиграй 20 раз",
need=20,
reward={
"бокс": 3,
},
),
Achievement(
name="друзья навеки",
emoji="🫂",
desc="пригласи друга по твоей реферальной ссылке и раздели веселье вместе с другом",
need=1,
reward={
"буст": 2,
},
),
]
20 changes: 19 additions & 1 deletion src/base/player.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,21 @@
from base.weather import get_weather

from helpers.exceptions import ItemIsCoin, NoResult
from helpers.markups import InlineMarkup
from helpers.utils import (
Loading,
award_user_achievement,
calc_xp_for_level,
from_user,
get_achievement,
get_item,
get_item_count_for_rarity,
get_time_difference_string,
get_item_emoji,
get_user_tag,
increment_achievement_progress,
utcnow,
)
from helpers.markups import InlineMarkup

from database.funcs import BaseDB, database, T as ModelsType
from database.models import (
Expand Down Expand Up @@ -120,6 +123,8 @@ def check_user_stats(user: UserModel, chat_id: Union[str, int, None] = None):
if user.coin < 0:
user.coin = 0

check_achievements(user)

# TODO edit
# tg_user = bot.get_chat(user.id)
# if user.name != tg_user.first_name:
Expand Down Expand Up @@ -651,6 +656,7 @@ def street(call: CallbackQuery, user: UserModel):
user.mood -= random.randint(3, 6)
user.met_mob = False
database.users.update(**user.to_dict())
increment_achievement_progress(user, "бродяга")

try:
user_notification = database.notifications.get(**{"owner": user._id})
Expand Down Expand Up @@ -719,6 +725,7 @@ def work(call: CallbackQuery, user: UserModel):
user.mood -= random.randint(3, 6)

database.users.update(**user.to_dict())
increment_achievement_progress(user, "работяга")

try:
user_notification = database.notifications.get(**{"owner": user._id})
Expand Down Expand Up @@ -758,7 +765,9 @@ def sleep(call: CallbackQuery, user: UserModel):
user.xp += random.uniform(1.5, 2.0)
user.state = None
user.action_time = utcnow()

database.users.update(**user.to_dict())
increment_achievement_progress(user, "сонный")

mess = "Охх, хорошенько поспал"
bot.edit_message_text(mess, call.message.chat.id, call.message.id)
Expand Down Expand Up @@ -801,7 +810,9 @@ def game(call: CallbackQuery, user: UserModel):
user.mood *= 2
user.state = None
user.action_time = utcnow()

database.users.update(**user.to_dict())
increment_achievement_progress(user, "игроман")

mess = "Как же хорошо было играть 😊"
bot.edit_message_text(mess, call.message.chat.id, call.message.id)
Expand All @@ -823,3 +834,10 @@ def generate_daily_gift(user: UserModel):
daily_gift.next_claimable_at = utcnow() + timedelta(days=1)
database.daily_gifts.update(**daily_gift.to_dict())
return daily_gift


def check_achievements(user: UserModel):
for key in list(user.achievement_progress):
ach = get_achievement(key.replace("-", " "))
if ach.check(user):
award_user_achievement(user, ach)
46 changes: 45 additions & 1 deletion src/bot/callback.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@
)
from base.items import items_list
from helpers.utils import (
achievement_progress,
check_user_subscription,
get_achievement,
get_item_count_for_rarity,
get_item_emoji,
get_middle_item_price,
Expand All @@ -44,7 +46,7 @@
from database.models import DogModel
from database.funcs import database

from config import bot
from config import bot, logger


@bot.callback_query_handler(lambda c: c.data.startswith("dog"))
Expand Down Expand Up @@ -875,3 +877,45 @@ def transfer_callback(call: CallbackQuery):
database.users.update(**reply_user.to_dict())

bot.send_message(call.message.chat.id, mess)


@bot.callback_query_handler(lambda c: c.data.startswith("achievements"))
def achievements_callback(call: CallbackQuery):
data = call.data.split(" ")

if data[-1] != str(call.from_user.id):
return

user = database.users.get(id=call.from_user.id)

if data[1] == "view":
ach = get_achievement(data[2])
mess = f"<b>{ach.emoji} {ach.name}</b>\n\n"
mess += f"<i>{ach.desc}</i>\n\n"
mess += f"{achievement_progress(user, ach.name)}"

logger.debug(user.achievement_progress)

markup = quick_markup(
{"Назад": {"callback_data": f"achievements main {user.id}"}}
)

bot.edit_message_text(
mess, call.message.chat.id, call.message.id, reply_markup=markup
)
elif data[1] == "main":
mess = "Достижения"

markup = InlineMarkup.achievements(user)

bot.edit_message_text(
mess, call.message.chat.id, call.message.id, reply_markup=markup
)

elif data[1] == "filter":
filter = data[2]
markup = InlineMarkup.achievements_view(user, filter) # type: ignore

bot.edit_message_reply_markup(
call.message.chat.id, call.message.id, reply_markup=markup
)
15 changes: 15 additions & 0 deletions src/bot/handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
get_item_emoji,
get_item,
Loading,
increment_achievement_progress,
send_channel_subscribe_message,
utcnow,
)
Expand Down Expand Up @@ -109,6 +110,8 @@ def start(message: Message):
coin = random.randint(5000, 15000)
ref_user.coin += coin
database.users.update(**ref_user.to_dict())
increment_achievement_progress(ref_user, "друзья навеки")

bot.send_message(
ref_user.id,
(
Expand Down Expand Up @@ -1008,6 +1011,16 @@ def time_cmd(message: Message):
bot.reply_to(message, mess)


@bot.message_handler(commands=["achievements"])
def achievements_cmd(message: Message):
user = database.users.get(id=message.from_user.id)

markup = InlineMarkup.achievements(user)

mess = "Достижения"
bot.reply_to(message, mess, reply_markup=markup)


# ---------------------------------------------------------------------------- #


Expand Down Expand Up @@ -1066,3 +1079,5 @@ def text_message_handler(message: Message):
home_cmd(message)
case "рынок":
market_cmd(message)
case "достижения" | "ачивки":
achievements_cmd(message)
7 changes: 7 additions & 0 deletions src/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
from typing import Final
from datetime import UTC, datetime

from dns import resolver

from redis import Redis
from dotenv import load_dotenv

Expand All @@ -17,6 +19,11 @@

load_dotenv()

# NOTE: Это для termux
resolver.default_resolver = resolver.Resolver(configure=False)
resolver.default_resolver.nameservers = ["8.8.8.8"]


with open("version") as f:
version: Final = Version.parse(f.read())

Expand Down
4 changes: 4 additions & 0 deletions src/database/funcs.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from helpers.exceptions import NoResult
from config import DB_NAME, DB_URL, REDIS_URL
from database.models import (
AchievementModel,
MarketItemModel,
NotificationModel,
UserModel,
Expand Down Expand Up @@ -40,6 +41,7 @@
notifications = db.get_collection("notifications")
market_items = db.get_collection("market_items")
daily_gifts = db.get_collection("daily_gifts")
achievements = db.get_collection("achievements")


T = TypeVar(
Expand All @@ -53,6 +55,7 @@
NotificationModel,
MarketItemModel,
DailyGiftModel,
AchievementModel,
)


Expand Down Expand Up @@ -100,6 +103,7 @@ def __init__(self) -> None:
self.notifications = BaseDB(notifications, NotificationModel)
self.market_items = BaseDB(market_items, MarketItemModel)
self.daily_gifts = BaseDB(daily_gifts, DailyGiftModel)
self.achievements = BaseDB(achievements, AchievementModel)


database = DataBase()
Expand Down
11 changes: 11 additions & 0 deletions src/database/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ class UserModel(BaseModel):
last_advert_time = Field(datetime, nullable=True)
adverts_count = Field(int, default=0)
last_active_time = Field(datetime, default=_utcnow())
achievement_progress: dict[str, int] = Field(dict, default={}) # type: ignore

def __init__(self, **kwargs) -> None:
super().__init__(**kwargs)
Expand Down Expand Up @@ -248,4 +249,14 @@ def __init__(self, **kwargs) -> None:
super().__init__(**kwargs)


class AchievementModel(BaseModel):
_id = Field(ObjectId)
owner = Field(ObjectId)
name = Field(str)
created_at = Field(datetime, default=_utcnow())

def __init__(self, **kwargs) -> None:
super().__init__(**kwargs)


del _utcnow
35 changes: 35 additions & 0 deletions src/helpers/datatypes.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
from typing import Any, Dict, List, Optional, Tuple

import transliterate

from database.models import UserModel
from helpers.enums import ItemRarity, ItemType, WeatherType

# ---------------------------------- Weather --------------------------------- #
Expand Down Expand Up @@ -158,3 +160,36 @@ def __str__(self) -> str:

def translit(self) -> str:
return transliterate.translit(self.name, reversed=True)


# ------------------------------- achievements ------------------------------- #


class Achievement:
def __init__(
self,
/,
name: str,
emoji: str,
desc: str,
need: int,
reward: dict[str, int],
) -> None:
self.name = name
self.emoji = emoji
self.desc = desc
self.need = need
self.key = name.strip().replace(" ", "-")
self.reward = reward

def __str__(self) -> str:
return f"{self.name}"

def check(self, user: UserModel):
progress = user.achievement_progress.get(self.key, 0)
if progress >= self.need:
return True
return False

def translit(self) -> str:
return transliterate.translit(self.key, reversed=True)
4 changes: 4 additions & 0 deletions src/helpers/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,7 @@ class ItemIsCoin(Exception):

class QuestNotFound(Exception):
pass


class AchievementNotFoundError(Exception):
pass
Loading

0 comments on commit 165feaf

Please sign in to comment.