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>
89 lines
3.2 KiB
Python
89 lines
3.2 KiB
Python
"""Carry the newest logged weight into the budget's stored weight.
|
|
|
|
The Body weight log (:mod:`diet_guard._body_store`) holds every weigh-in --
|
|
the phone's morning ones, ingested each tick by :mod:`diet_guard._sync_body`,
|
|
and any typed on either device. Its newest entry is what the protein target
|
|
here is derived from (``_budget_derived.protein_target_g``), so after each
|
|
successful ``sync`` the stored ``w`` is refreshed from it.
|
|
|
|
Only ``w`` moves. The kcal budget is never recomputed -- the Body tab's
|
|
calorie table is informational, and the budget stays the number the user
|
|
edits. ``t`` is refreshed with ``w`` because both ride the same edit
|
|
timestamp into the per-field last-write-wins merge (``sync_merge._budget``);
|
|
a new weight under an old ``t`` would lose to every other device on the next
|
|
merge.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from typing import TYPE_CHECKING
|
|
|
|
from diet_guard._body_store import newest_weight
|
|
from diet_guard._budget import _now_local, read_raw_record, write_raw_record
|
|
|
|
if TYPE_CHECKING:
|
|
from collections.abc import Callable
|
|
|
|
__all__ = ["refresh_weight_from_log", "update_weight"]
|
|
|
|
# Below this the scale and the record agree; a rewrite would only churn ``t``.
|
|
_SAME_WEIGHT_KG = 0.05
|
|
|
|
|
|
def update_weight(kg: float) -> bool:
|
|
"""Set the budget record's stored weight to ``kg``; False when no budget.
|
|
|
|
Writes through the raw accessors rather than :func:`_budget.write_budget`
|
|
on purpose: that path stamps a budget change into the effective-from
|
|
history, and the budget has not changed.
|
|
"""
|
|
record = read_raw_record()
|
|
if record is None:
|
|
return False
|
|
record["w"] = round(float(kg), 1)
|
|
record["t"] = _now_local().isoformat(timespec="seconds")
|
|
write_raw_record(record)
|
|
return True
|
|
|
|
|
|
def _budget_edit_day(record: dict[str, object]) -> str:
|
|
"""The local ``yyyy-mm-dd`` of the record's last edit, or '' when unknown."""
|
|
return str(record.get("t", ""))[:10]
|
|
|
|
|
|
def refresh_weight_from_log(emit: Callable[[str], None]) -> None:
|
|
"""Apply the weight log's newest weigh-in to the stored weight, if newer.
|
|
|
|
Skipped, silently, when: the log is empty; no budget exists; the
|
|
weigh-in is not from a *later* day than the budget's last edit; or it
|
|
matches the stored weight within :data:`_SAME_WEIGHT_KG`.
|
|
|
|
The day comparison is strict. A weigh-in happens in the morning and a
|
|
manual budget edit at any time of day, and ``t`` carries only the day's
|
|
granularity worth trusting here, so on a shared day the budget edit is
|
|
taken as the more recent human action and kept. The cost is one day of
|
|
lag in that one case; the alternative overwrites an edit made hours
|
|
after the weigh-in.
|
|
|
|
Args:
|
|
emit: One-line output sink, given a line only when a write happened.
|
|
"""
|
|
newest = newest_weight()
|
|
if newest is None:
|
|
return
|
|
day, kg = newest
|
|
record = read_raw_record()
|
|
if record is None:
|
|
return
|
|
if day <= _budget_edit_day(record):
|
|
return
|
|
stored = record.get("w")
|
|
if (
|
|
isinstance(stored, (int, float))
|
|
and not isinstance(stored, bool)
|
|
and abs(float(stored) - kg) < _SAME_WEIGHT_KG
|
|
):
|
|
return
|
|
update_weight(kg)
|
|
emit(f"weight: {kg} kg from the weight log ({day}).")
|