diff --git a/app/services/dailyquests.py b/app/services/dailyquests.py index 3fe305d..9c97a4d 100644 --- a/app/services/dailyquests.py +++ b/app/services/dailyquests.py @@ -34,6 +34,42 @@ class DailyQuestsService: """ DEFAULT_DAILY_COUNT = 3 + + def _choose_by_difficulty(self, pool: List[dict]) -> List[dict]: + # группируем по сложности + buckets = {"easy": [], "medium": [], "hard": []} + for it in pool: + diff = str(it.get("difficulty", "")).lower() + if diff in buckets: + buckets[diff].append(it) + + chosen: List[dict] = [] + + # по 1 из каждой сложности, weighted, без повторов + for diff in ("easy", "medium", "hard"): + items = buckets[diff] + if not items: + continue + pick = random.choices( + items, + weights=[max(1, int(x.get("weight", 1) or 1)) for x in items], + k=1 + )[0] + chosen.append(pick) + + # если чего-то не хватило (например нет hard в пуле) — + # добиваем случайными из оставшихся enabled, чтобы всё равно было 3 + need_total = 3 + if len(chosen) < need_total: + already = {c.get("key") for c in chosen} + rest = [x for x in pool if x.get("key") not in already] + if rest: + extra = self._weighted_sample_without_replacement( + rest, k=min(need_total - len(chosen), len(rest)) + ) + chosen.extend(extra) + + return chosen async def get_status(self, username: str) -> dict: now_utc = datetime.now(timezone.utc) @@ -228,9 +264,7 @@ class DailyQuestsService: await user_daily_quests_collection.insert_one(doc) return doc - count = self.DEFAULT_DAILY_COUNT - # weighted random without replacement - chosen = self._weighted_sample_without_replacement(pool, k=min(count, len(pool))) + chosen = self._choose_by_difficulty(pool) quests = [] for tpl in chosen: