{% extends "base.html" %} {% block title %}Health ยท {{ app_name }}{% endblock %} {% import "_chart.html" as ch %} {# ๐Ÿ”ด GAPS ARE DRAWN AS BREAKS, NOT JOINED โ€” in core/chart.py, which is where that rule now lives for the whole app. history() returns a null for a day with no reading, and the natural single polyline would draw a straight line across a fortnight nobody measured: a picture of steady progress invented out of missing data. Same contract as the tiles above โ€” unknown must not look like a value. #} {% block body %}

๐Ÿ’š Health what your body did, and what the game did about it

{% if s.stale %}

The sync has stopped

Nothing has arrived {% if s.last_sync %}since {{ s.last_sync|local }} ({{ s.last_sync|rel(now) }}){% else %}ever{% endif %}. Rules are not firing, and the numbers below โ€” if there are any โ€” are old.

Check sync-health-to-latch.py on the apps pod.

{% endif %} {% if s.recovery.on %}

๐Ÿ›Ÿ Recovery day

{% for r in s.recovery.reasons %}

โ€œ{{ r.line }}โ€

{% endfor %}

Penalties are held back today. Rewards still count โ€” moving at all on a day like this is worth more, not less.

{% endif %}

{{ 'Today' if s.is_today else 'Latest readings' }} {{ s.day }}{% if not s.is_today %} ยท {{ s.lag }} day{{ 's' if s.lag != 1 }} behind โ€” Apple exports overnight, so today fills in tomorrow{% endif %}

{% for t in s.tiles %}
{{ t.label }} {%- if not t.known -%}โ€” {%- elif t.metric == 'mood_valence' -%}{{ '%+.2f'|format(t.value) }} {%- elif t.value == t.value|round(0) -%}{{ t.value|int }} {%- else -%}{{ '%.1f'|format(t.value) }}{%- endif -%} {% if t.known and t.unit %}{{ t.unit }}{% endif %} {{ t.source if t.known else 'no reading' }}
{% endfor %}
{% if not s.any %}

Nothing measured for today yet. That is not the same as a zero โ€” no rule can fire on a day nobody measured, in either direction.

{% endif %}
{% for q in s.quiet %}

โš  {{ q.label }} stopped

{% if q.last %}Nothing logged for {{ q.days }} days โ€” last was {{ q.last }}. {% else %}Never logged.{% endif %}

Shown rather than hidden on purpose: a blank space reads as "fine", and the point of tracking this is to notice when it stops.

{% endfor %}

Rules

{% for r in s.rules %} {% endfor %}
ruletodayreadingeffect
{{ r.rule.title }} {%- if r.state is none -%}unknown {%- elif r.withheld and r.state -%}held back {%- elif r.fired -%}fired {%- elif r.state -%}ready {%- else -%}no{%- endif -%} {%- if r.value is none -%}no reading {%- else -%}{{ '%g'|format(r.value) }} vs {{ '%g'|format(r.threshold) }}{%- endif -%} {%- if r.rule.xp %}+{{ r.rule.xp }} xp{% endif -%} {%- if r.rule.seconds %}{{ ' ยท ' if r.rule.xp }}{{ (r.rule.seconds // 60)|abs }} min {{ 'off' if r.rule.seconds < 0 else 'on' }}{% endif -%} {%- if r.rule.recovery %} eases the day{% endif -%}

Last 30 days to {{ trend_end or 'โ€”' }}

{# Ends at the last day the export covered, not today: Apple delivers overnight, so a chart drawn to today falls off a cliff at the right-hand edge every single day. #}
{% for c in trends %}

{{ c.title }}

{{ ch.line(c) }}
{% endfor %}

A day with no reading is a break in the line, never a zero โ€” about a quarter of days carry none. ๐Ÿ“– how these are drawn

{% endblock %}