""" set_campaign_time.py — изменение игрового времени. Экспортирует функцию set_campaign_time(debug_description, requests), которую вызывает тул с фронта. requests — список объектов вида: { "mode": "absolute" | "shift", # режим: absolute – установка, shift – сдвиг (default "shift") "year": 1492, # при absolute – год, при shift – сдвиг лет "month": 1, # при absolute – месяц (число 1-12 или русское название), при shift – сдвиг месяцев (число) "day": 1, # при absolute – день, при shift – сдвиг дней "hour": 0, # при absolute – час, при shift – сдвиг часов } При mode="absolute" можно передать только часть полей, остальные останутся без изменений. Поле month при mode="absolute" принимает: - целое число от 1 до 12 - строку, содержащую число (например "3") - русское название месяца (регистр не важен): 1: Хаммер 2: Алтуриак 3: Чес 4: Тарсак 5: Миртул 6: Киторн 7: Флеймрул 8: Элейнт (допускается "Элизис") 9: Элесиас 10: Марпенот 11: Уктар (допускается "Укта") 12: Найтол При mode="shift" month должен быть числом (целым, может быть отрицательным). Возвращает строку в формате Markdown с результатом изменения и списком праздников на неделю. """ from typing import TypedDict try: from typing_extensions import TypedDict except ImportError: from typing import TypedDict from time_utils import ( get_campaign_time as get_time, set_campaign_time as set_time_absolute, shift_campaign_time, MONTH_NAMES_RU, parse_month, get_week_holidays, get_holiday, is_leap_year, ) class TimeChangeRequest(TypedDict, total=False): """ Запрос на изменение игрового времени. Поля: mode: Режим операции: "absolute" – установить абсолютное время (используются year, month, day, hour как новые значения); "shift" – сдвинуть текущее время на указанные значения (year, month, day, hour интерпретируются как дельты). По умолчанию: "shift". year: При mode="absolute" – год (целое >0). При mode="shift" – сдвиг в годах (может быть отрицательным). month: При mode="absolute" – месяц (число 1-12 или русское название). При mode="shift" – сдвиг в месяцах (целое, может быть отрицательным). Допустимые русские названия (регистр не важен): 1: Хаммер 2: Алтуриак 3: Чес 4: Тарсак 5: Миртул 6: Киторн 7: Флеймрул 8: Элейнт (также принимается "Элизис") 9: Элесиас 10: Марпенот 11: Уктар (также принимается "Укта") 12: Найтол day: При mode="absolute" – день (1–30). При mode="shift" – сдвиг в днях (может быть отрицательным). hour: При mode="absolute" – час (0–23). При mode="shift" – сдвиг в часах (может быть отрицательным). """ mode: str # "absolute" | "shift", default "shift" year: int month: int | str day: int hour: int def _format_time(year: int, month: int, day: int, hour: int) -> str: month_name = MONTH_NAMES_RU.get(month, str(month)) return f"{day} {month_name} {year} DR, {hour:02d}:00" def _format_holidays_section(year: int, month: int, day: int) -> str: holidays = get_week_holidays(year, month, day) if not holidays: return "📅 **Ближайшие праздники:** нет" lines = ["📅 **Ближайшие праздники:**"] for m, d, desc, when in holidays: month_name = MONTH_NAMES_RU.get(m, str(m)) lines.append(f"- **{when}** ({d} {month_name}): {desc}") return "\n".join(lines) def set_campaign_time(debug_description: str, requests: list[TimeChangeRequest]) -> str: if not requests: requests = [{}] sections = [] for idx, req in enumerate(requests, start=1): mode = req.get("mode", "shift") old_time = get_time() old_str = _format_time(old_time["year"], old_time["month"], old_time["day"], old_time["hour"]) if mode == "absolute": new_year = old_time["year"] new_month = old_time["month"] new_day = old_time["day"] new_hour = old_time["hour"] if "year" in req: new_year = req["year"] if "month" in req: try: new_month = parse_month(req["month"]) except (ValueError, TypeError) as e: sections.append(f"### ❌ Ошибка в запросе #{idx}\n{e}") continue if "day" in req: new_day = req["day"] if "hour" in req: new_hour = req["hour"] if new_year <= 0: sections.append(f"### ❌ Ошибка в запросе #{idx}\nГод должен быть > 0, получено {new_year}.") continue if not (1 <= new_month <= 12): sections.append(f"### ❌ Ошибка в запросе #{idx}\nМесяц должен быть 1-12, получено {new_month}.") continue if not (1 <= new_day <= 30): sections.append(f"### ❌ Ошибка в запросе #{idx}\nДень должен быть 1-30, получено {new_day}.") continue if not (0 <= new_hour <= 23): sections.append(f"### ❌ Ошибка в запросе #{idx}\nЧас должен быть 0-23, получено {new_hour}.") continue success = set_time_absolute(new_year, new_month, new_day, new_hour) if success: new_time = get_time() new_str = _format_time(new_time["year"], new_time["month"], new_time["day"], new_time["hour"]) sections.append( f"### 📅 Установка времени #{idx}\n" f"- Старое: {old_str}\n" f"- **Новое:** {new_str}" ) else: sections.append(f"### ❌ Ошибка записи времени #{idx}") else: # shift delta_year = req.get("year", 0) delta_month = req.get("month", 0) delta_day = req.get("day", 0) delta_hour = req.get("hour", 0) if "month" in req: try: delta_month = int(req["month"]) except (ValueError, TypeError): sections.append(f"### ❌ Ошибка в запросе #{idx}\nПри mode='shift' month должен быть числом, получено {req['month']}.") continue if delta_year == 0 and delta_month == 0 and delta_day == 0 and delta_hour == 0: current = get_time() current_str = _format_time(current["year"], current["month"], current["day"], current["hour"]) sections.append( f"### 🕰️ Текущее время #{idx}\n" f"**Время:** {current_str}" ) else: new_time = shift_campaign_time(delta_year, delta_month, delta_day, delta_hour) new_str = _format_time(new_time["year"], new_time["month"], new_time["day"], new_time["hour"]) parts = [] if delta_year: parts.append(f"{delta_year:+d} лет") if delta_month: parts.append(f"{delta_month:+d} месяцев") if delta_day: parts.append(f"{delta_day:+d} дней") if delta_hour: parts.append(f"{delta_hour:+d} часов") shift_desc = ", ".join(parts) if parts else "0" sections.append( f"### ⏳ Сдвиг времени #{idx}\n" f"- Сдвиг: {shift_desc}\n" f"- Старое: {old_str}\n" f"- **Новое:** {new_str}" ) final_time = get_time() holidays_section = _format_holidays_section( final_time["year"], final_time["month"], final_time["day"] ) result = "\n\n---\n\n".join(sections) result += f"\n\n---\n\n{holidays_section}" return result if __name__ == "__main__": import sys if hasattr(sys.stdout, 'reconfigure'): sys.stdout.reconfigure(encoding='utf-8') result = set_campaign_time("тест", [ {"mode": "shift", "day": 1, "hour": 5}, {"mode": "absolute", "year": 1492, "month": 1, "day": 1, "hour": 0}, {"mode": "absolute", "hour": 12}, {"mode": "absolute", "month": "Миртул", "day": 15}, {"mode": "absolute", "month": "Укта"}, {}, ]) print(result)