1 """Utility functions for Habitica."""
3 from __future__
import annotations
7 from typing
import TYPE_CHECKING, Any
9 from dateutil.rrule
import (
30 def next_due_date(task: dict[str, Any], last_cron: str) -> datetime.date |
None:
31 """Calculate due date for dailies and yesterdailies."""
33 if task[
"everyX"] == 0
or not task.get(
"nextDue"):
37 startdate =
to_date(task[
"startDate"])
42 if task[
"isDue"]
and not task[
"completed"]:
46 if task[
"frequency"] ==
"daily" or (
47 task[
"frequency"]
in (
"monthly",
"yearly")
and task[
"daysOfMonth"]
52 task[
"frequency"]
in (
"weekly",
"monthly")
53 and (nextdue :=
to_date(task[
"nextDue"][0]))
54 and startdate > nextdue
56 return to_date(task[
"nextDue"][1])
58 return to_date(task[
"nextDue"][0])
61 def to_date(date: str) -> datetime.date |
None:
62 """Convert an iso date to a datetime.date object."""
64 return dt_util.as_local(datetime.datetime.fromisoformat(date)).
date()
69 return dt_util.as_local(
70 datetime.datetime.strptime(date,
"%a %b %d %Y %H:%M:%S %Z%z")
77 """Get list of related automations and scripts."""
83 FREQUENCY_MAP = {
"daily": DAILY,
"weekly": WEEKLY,
"monthly": MONTHLY,
"yearly": YEARLY}
84 WEEKDAY_MAP = {
"m": MO,
"t": TU,
"w": WE,
"th": TH,
"f": FR,
"s": SA,
"su": SU}
88 """Build rrule string."""
90 rrule_frequency = FREQUENCY_MAP.get(task[
"frequency"], DAILY)
92 WEEKDAY_MAP[day]
for day, is_active
in task[
"repeat"].items()
if is_active
96 if rrule_frequency == MONTHLY
and task[
"daysOfMonth"]
101 if rrule_frequency == MONTHLY
and task[
"weeksOfMonth"]:
102 bysetpos = task[
"weeksOfMonth"]
103 weekdays = weekdays
if weekdays
else [MO]
106 freq=rrule_frequency,
107 interval=task[
"everyX"],
108 dtstart=dt_util.start_of_local_day(
109 datetime.datetime.fromisoformat(task[
"startDate"])
111 byweekday=weekdays
if rrule_frequency
in [WEEKLY, MONTHLY]
else None,
112 bymonthday=bymonthday,
118 r"""Extract and return the recurrence rule portion of an RRULE.
120 This function takes an RRULE representing a task's recurrence pattern,
121 builds the RRULE string, and extracts the recurrence rule part.
123 'DTSTART:YYYYMMDDTHHMMSS\nRRULE:FREQ=YEARLY;INTERVAL=2'
133 The recurrence rule portion of the RRULE string, starting with 'FREQ='.
137 >>> rule = get_recurrence_rule(task)
139 'FREQ=YEARLY;INTERVAL=2'
142 return str(recurrence).split(
"RRULE:")[1]
146 user: dict[str, Any], content: dict[str, Any], attribute: str
147 ) -> dict[str, float]:
148 """Get modifiers contributing to strength attribute."""
164 if (equipped := user[
"items"][
"gear"][
"equipped"].
get(gear))
165 and (stats := content[
"gear"][
"flat"].
get(equipped))
171 if (equipped := user[
"items"][
"gear"][
"equipped"].
get(gear))
172 and (stats := content[
"gear"][
"flat"].
get(equipped))
173 and stats[
"klass"] == user[
"stats"][
"class"]
177 "level":
min(floor(user[
"stats"][
"lvl"] / 2), 50),
178 "equipment": equipment,
179 "class": class_bonus,
180 "allocated": user[
"stats"][attribute],
181 "buffs": user[
"stats"][
"buffs"][attribute],
186 user: dict[str, Any], content: dict[str, Any], attribute: str
188 """Get total attribute points."""
list[str] automations_with_entity(HomeAssistant hass, str entity_id)
web.Response get(self, web.Request request, str config_key)
list[str] entity_used_in(HomeAssistant hass, str entity_id)
str get_recurrence_rule(rrule recurrence)
datetime.date|None next_due_date(dict[str, Any] task, str last_cron)
datetime.date|None to_date(str date)
rrule build_rrule(dict[str, Any] task)
dict[str, float] get_attribute_points(dict[str, Any] user, dict[str, Any] content, str attribute)
int get_attributes_total(dict[str, Any] user, dict[str, Any] content, str attribute)
list[str] scripts_with_entity(HomeAssistant hass, str entity_id)