mirror of
https://github.com/kuhyx/diet-guard.git
synced 2026-11-10 18:07:20 +01:00
Some checks failed
dependency freshness / dependencies on newest stable (push) Has been cancelled
file-length / file length <= 250 lines (push) Has been cancelled
md-naming / markdown naming convention (push) Has been cancelled
pre-commit / pre-commit (${{ matrix.group }}) (mypy, mypy, ) (push) Has been cancelled
pre-commit / pre-commit (${{ matrix.group }}) (pylint, pylint, ) (push) Has been cancelled
pre-commit / pre-commit (${{ matrix.group }}) (rest, , mypy,pylint) (push) Has been cancelled
Tests / test (push) Has been cancelled
release-apk / release (APK) (push) Has been cancelled
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
70 lines
2.2 KiB
Python
70 lines
2.2 KiB
Python
"""The calorie goal the user last picked -- remembered and synced.
|
|
|
|
Stored as one extra field, ``goal``, on the synced ``profile`` record, so the
|
|
sentence "To lose 0.5 kg / week on Moderate eat ..." reads the same on the PC
|
|
gate and the phone. Each part is validated on read: an unknown direction,
|
|
unit or activity (a peer on a newer version, a typo) falls back to that part
|
|
of :data:`~diet_guard._body_energy.DEFAULT_GOAL` rather than breaking the tab.
|
|
|
|
KEEP IN SYNC WITH ``app/lib/services/body_prefs.dart``.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from dataclasses import replace
|
|
|
|
from diet_guard._body_energy import (
|
|
ACTIVITY_CHOICES,
|
|
DEFAULT_GOAL,
|
|
DIRECTIONS,
|
|
TIME_UNITS,
|
|
WEIGHT_UNITS,
|
|
Goal,
|
|
)
|
|
from diet_guard._body_store import as_number, read_body, set_profile
|
|
|
|
__all__ = ["GOAL_FIELD", "goal_from_json", "goal_to_json", "saved_goal", "set_goal"]
|
|
|
|
GOAL_FIELD = "goal"
|
|
|
|
|
|
def goal_to_json(goal: Goal) -> dict[str, object]:
|
|
"""The wire/disk form (short keys)."""
|
|
return {
|
|
"dir": goal.direction,
|
|
"amt": goal.amount,
|
|
"wu": goal.weight_unit,
|
|
"tu": goal.time_unit,
|
|
"act": goal.activity,
|
|
}
|
|
|
|
|
|
def goal_from_json(raw: object) -> Goal:
|
|
"""Parse a stored goal part by part, defaulting whatever is unusable."""
|
|
if not isinstance(raw, dict):
|
|
return DEFAULT_GOAL
|
|
amount = as_number(raw.get("amt"))
|
|
goal = DEFAULT_GOAL
|
|
if raw.get("dir") in DIRECTIONS:
|
|
goal = replace(goal, direction=str(raw["dir"]))
|
|
if amount is not None and amount >= 0:
|
|
goal = replace(goal, amount=amount)
|
|
if raw.get("wu") in WEIGHT_UNITS:
|
|
goal = replace(goal, weight_unit=str(raw["wu"]))
|
|
if raw.get("tu") in TIME_UNITS:
|
|
goal = replace(goal, time_unit=str(raw["tu"]))
|
|
if raw.get("act") in ACTIVITY_CHOICES:
|
|
goal = replace(goal, activity=str(raw["act"]))
|
|
return goal
|
|
|
|
|
|
def saved_goal() -> Goal:
|
|
"""The remembered goal (the default until one is saved)."""
|
|
cell = read_body()["profile"].get(GOAL_FIELD)
|
|
return goal_from_json(cell.get("v") if isinstance(cell, dict) else None)
|
|
|
|
|
|
def set_goal(goal: Goal) -> None:
|
|
"""Remember (and sync) ``goal``."""
|
|
set_profile(**{GOAL_FIELD: goal_to_json(goal)})
|