About your scores

This app turns the data your phone and wearables already collect — sleep, heart rate, and exercise — into four daily numbers that try to answer one question: how is your body doing today, and what should you do with that information?

We try to be honest about what these numbers can and can’t tell you. They are decision aids, not diagnoses. If something feels off in your body, trust your body over the score.

Your profile matters

When you first open the app, you select a Physiological Profile — Athlete, Active, or Sedentary — that tunes how we interpret your data. Different activity profiles show different recovery patterns, so the thresholds we use to score you are customized.

Why profiles exist. An athlete’s HRV is normally more stable than a sedentary person’s, so a genuine departure means more for an athlete — we don’t compare them to the same bar. Likewise, someone training to peak benefits from tighter circadian consistency targets than someone with a relaxed schedule. Profiles let us keep scores fair across different lifestyles.


A note on measurement

Wearables estimate sleep stages, HRV, and nocturnal physiology indirectly using probabilistic algorithms. These estimates may contain significant measurement error compared to clinical systems like polysomnography or ECG. The scores shown here are fitness-focused estimates, not clinical measurements. Profile settings optimize estimated recovery signals, which are influenced by many factors (stress, sleep environment, caffeine, hydration, illness, etc.). Scores are readiness indicators, not diagnoses.


The four scores at a glance

Score What it answers Range
Sleep Score How restorative was last night’s sleep? 0–100
Circadian Consistency How regular is your sleep schedule? 0–100
Readiness How prepared are you based on sleep, recovery, and load? 0–100
Training Readiness How prepared are you after residual workout fatigue? 0–100

You’ll see the scores on your dashboard once enough data has been collected. Training Readiness is hidden by default until you enable its card. Until then, we’ll show you what we have and explain what’s missing.


Sleep Score

A 100-point summary of last night’s sleep, made of four parts (under the default Balanced profile):

Weight emphasis profiles

You can customize the relative emphasis of each sleep component in Settings to suit your recovery focus (Balanced, Duration Focused, Recovery Focused, Architecture Focused, or Continuity Focused). Changing your weight profile requires running the Recalculate scores action in Settings to apply the new weighting across your history.

Sleep Regularity multiplier

Your sleep score incorporates Sleep Regularity as a penalty-only multiplier between 0.92 and 1.00 derived from your circadian consistency score. Consistent sleep timing preserves 100% of your score (multiplier 1.00), while irregular schedules incur a mild proportional deduction. During baseline calibration or when circadian data is missing, the multiplier remains neutral (1.00).

If a source provides a sleep session with no stage records, Readylytics uses the raw session span as total sleep duration. Because Architecture and Fragmentation are unavailable, the Sleep Score renormalizes the remaining sub-scores (Duration and Restoration) according to your active weight profile. This differs from suspicious but non-empty stage data: the source supplied stages, but their distribution failed plausibility checks.

Reading the score

Deep and REM sleep targets — age matters

As you age, the amount of deep sleep naturally declines. We adjust your targets based on your age so you’re never unfairly compared to a younger person.

Age range Deep sleep target REM sleep target
18–29 20% 22%
30–49 18% 21%
50–59 15% 20%
60+ 12% 19%

These ranges come from polysomnography studies in healthy populations. They represent the healthy mid-range; your personal healthy normal may sit anywhere within your age band. Note that the age-related decline in deep (slow-wave) sleep is much steeper than the decline in REM, which falls only modestly across adulthood (Ohayon 2004). We do not penalise you if your wearable reports unusual numbers — wearable stage detection is imperfect.

Biphasic sleep and naps

We fully support segmented or biphasic sleep. If you sleep in multiple blocks (like a main overnight sleep and an afternoon nap), your “core” sleep drives your recovery metrics (Restoration/HRV/RHR), while all supplemental sleep adds to your total Duration. This means naps will improve your Sleep Score by adding duration, but they won’t rewrite your overnight Readiness signal or baseline HRV.

HRV sensitivity by profile

Heart rate variability (HRV) is noisy on any single night. To avoid false positives, we only flag HRV as notably “high” or “low” once it crosses a Z-score threshold. While your personal baseline is still being learned (the Early Baseline phase), we estimate your day-to-day variability from a population value tiered by profile, so the threshold shifts with it.

This tuning means a single noisy night isn’t treated as a signal as readily for a Sedentary person as the same Z-score would be for an Athlete, because higher baseline noise produces more large deviations by chance. Once your personal baseline matures (60+ nights), the Z-score is computed against your own standard deviation, which already accounts for your individual variability.

Implemented in: SleepScoringStrategy.kt, SleepArchitectureTargets.kt, ScoringConstants.kt

Restoration/HRV Z-scores implemented in: LoadScoringStrategy.kt, BaselineComputer.kt, HrvBaselineProvider.kt, RhrBaselineProvider.kt


Circadian Consistency

This score asks: do you go to bed and wake up at roughly the same times each day? Schedule regularity is independently linked to better metabolic, cognitive, and cardiovascular outcomes — sometimes more strongly than sleep duration itself (Windred et al. 2023, UK Biobank).

We compare each night’s bedtime and wake time to your typical (median) bedtime and wake time over the last 14 days. The bigger the deviation, the lower the daily score. The number you see is a 7-day rolling average so a single late night doesn’t tank it.

Profile-specific thresholds

How strict we are about “consistent” depends on your profile:

Profile Deviation threshold Interpretation
Athlete ±20 minutes Tight control for performance
Active ±30 minutes Standard regularity
Sedentary ±45 minutes Relaxed; normal life variation OK

Within each threshold band:

You can override the resolved threshold with your own value in Settings if the profile default doesn’t fit your schedule.

A caveat for biphasic sleepers. This metric is calibrated for people with one main sleep period per day. If you sleep in two segments by choice (e.g., 2:00–4:00 AM and then again at 6:00–7:00 AM), the score may misclassify your schedule. We exclude any single sleep period under 3 hours from the median calculation so naps don’t pull your “typical” times around — but this rule has imperfect coverage of every sleep pattern.

Implemented in: CircadianConsistencyRepository.kt, CircadianThresholdDefaults.kt


Readiness

A daily 0–100 composite number summarising three signals:

Readiness = 0.4 × Restoration (sRest) + 0.3 × Sleep Score + 0.3 × Load Score

Each component is described in its own section above. Restoration carries the largest single weight (0.4), so your overnight recovery markers are the biggest lever on Readiness — but a significant load spike or poor sleep will also pull the score down.

The Load Score (one of the three components) itself is based on your training load ratio:

We compute two rolling averages of your training load:

The ratio (ATL ÷ CTL) tells us whether you’ve recently spiked above your recent norm. Around 1.0 means you’re training in line with your fitness; substantially above 1.0 means a relative spike.

How we score the ratio

Tooltips

Emergency signals

When HRV is much lower than usual and resting heart rate is elevated for more than one day, readiness may be capped as a cautious possible-illness signal (which caps it at 50). When HRV is much higher than usual and resting heart rate is much lower than usual, the app treats this as an encouraging recovery signal rather than overreaching. Strong recovery signals do not cap Readiness. To ensure accuracy and filter out acute noise (e.g., alcohol or minor stress), the algorithm requires the thresholds to be breached on two consecutive nights (Mishra 2020, Le Meur 2013). This is informational only, not medical advice. Workout-impact and rest-day flags shown elsewhere are informational only and do not cap your Readiness number.

What we don’t do. We don’t penalise you for resting. A week of light activity will not drop Readiness; the score is designed for load spikes, not undertraining.

Implemented in: LoadScoringStrategy.kt, RasScoringStrategy.kt, ComputeSleepMetricsUseCase.kt


Training Readiness

Training Readiness is an optional, default-hidden Dashboard score. It keeps legacy Readiness unchanged while adding Residual Fatigue to the load branch. Residual Fatigue is a raw, unbounded, non-normalized, provisional, workout-only derived input: it feeds Training Readiness when available but does not modify legacy Readiness or Load Score.

AcuteLoadRecovery = clamp(100 * exp(-ResidualFatigue / S), 0, 100)

TrainingLoadReadiness = clamp(w * LoadScore + (1 - w) * AcuteLoadRecovery, 0, 100)

TrainingReadiness = existingReadinessCalculator(Restoration, Sleep, TrainingLoadReadiness, recoveryFlags)

At w = 1, Training Readiness equals the stored Readiness exactly, and Training Load Readiness preserves the source-matched Load Score.

When Residual Fatigue is unavailable, Acute Load Recovery is unavailable, Training Load Readiness equals Load Score, and Training Readiness equals Readiness.

Training Readiness uses the active Strain / Training Load source for its Load Score branch. Residual Fatigue remains workout-only and never includes everyday heart-rate load.

Edits to S and w remain pending until you choose Recalculate Training Readiness. The durable projection-only recalculation reads stored daily summaries; only success advances the applied values, so current scores stay on the last-applied settings during a run or failure.

The AI Advisor still uses Readiness, not Training Readiness. Training Readiness is excluded from Advisor/AI, Workouts card layouts, trends, insights, details/history, widgets, and standalone exports in this release.

Implemented in: ComputeTrainingReadinessUseCase.kt, TrainingReadinessProjectionRecomputeUseCase.kt, FinalSummaryAssembler.kt


Load Sources

Two independent settings control which heart-rate data feeds your strain/training-load metrics versus your Readylytics Activity Score (RAS):

Workout only counts heart-rate load from your logged exercise sessions only — the original behaviour.

Everyday heart-rate load also counts elevated heart rate outside workouts (e.g. from stress, illness, or heat) on top of your workout TRIMP. Your workout TRIMP is folded into this total exactly once — it is never double-counted. Sleep is always excluded from the everyday calculation.

For the everyday calculation, every waking, non-sleep, non-workout minute with at least one heart-rate sample is classified into a heart-rate zone using your configured zones/TRIMP settings — the same model used for workouts. Zone 0 minutes (below your Zone 1 threshold) are excluded from TRIMP but still counted toward coverage. Zone 1 and above minutes contribute TRIMP using the standard per-minute formula.

Both source variants are calculated and stored for every day, so switching either setting is instant — no recalculation or history rewrite is needed.

New installs default to Strain / Training Load = Workout only and RAS = Everyday heart-rate load. Existing users upgrading keep their prior behaviour automatically: the first time the app runs after upgrade, the RAS source is set to Workout only as a one-time default if you already have workout history — you can change it in Settings at any time.

Implemented in: EverydayHeartRateLoadCalculator.kt, LoadSourceSelector.kt, LoadSourceMode.kt


BMI and Body Fat

BMI (Body Mass Index) classifies your weight relative to height using WHO-aligned bands:

The Weight card’s BMI reference gauge uses visual anchors of 15, 21.7, and 35 so its midpoint is shown at 21.7. These anchors position the gauge only; they do not change the BMI status bands above.

Body Fat Percentage uses continuous, gender-specific bands when your profile records a biological sex:

If gender is set to Other, Prefer not to say, or is unset, we show a fixed 10–30% reference band centered on 20% instead of a gendered scale — values inside the band are Optimal, at or below 10% is Neutral, and above 30% is Poor.

The Body Fat card also shows a reference midpoint — a target value for your physiology profile, used only to position the marker on the gauge, not to change your status:

Reading the status. Optimal (green) and Neutral (informational) describe healthy or expected ranges; Warning flags dangerously low essential-fat levels, or a BMI that is either underweight or overweight — the same status covers both directions, so check the category label (not just the color) to see which one applies; Poor flags the obesity range for BMI or body fat.

The status colors on Weight and Body Fat trend charts use these same canonical bands. Visual reference anchors and profile markers never redefine a reading’s status.

Implemented in: BodyCompositionAssessment.kt, BmiService.kt, HealthMetricsService.kt, HealthMetricsCalculator.kt


Blood Pressure

The dashboard classifies each blood-pressure reading with an inclusive, component-wise ladder:

For example, 121/80, 120/81, and 129/89 are Neutral, while 130/90 is Warning. This is a dashboard status, not a diagnosis.

Blood-pressure trend charts obtain their component reference bands from this same ladder.

Implemented in: HealthMetricsService.kt


Overnight Oxygen Saturation

The dashboard card uses your overnight average oxygen saturation. Overnight oxygen saturation: below 90% Poor; 90–94% Warning; 95–97% Neutral; 98% and above Optimal.

This means an overnight average of 96% is Neutral. The status describes the displayed overnight average rather than a scoring-engine calculation.


Body Temperature

The dashboard card and Vitals trend chart show your overnight average body temperature (nightly average of Health Connect readings within your sleep-session window). This is an optional metric — it requires the separate READ_BODY_TEMPERATURE Health Connect permission, and the card stays hidden until you grant it.

Once you have 14 nights of readings, we show a rolling 14-day baseline — a plain trailing average of your own recent nights. Before that, the card shows “Calibrating” instead of a deviation badge. We compare today’s reading against that baseline and flag a day as elevated when it deviates by at least your configured elevated-deviation threshold (Settings, default 1.0°C, adjustable from 0.25°C to 1.5°C) in either direction — a wider swing than typical night-to-night noise.

This baseline is intentionally a simple average, not the log-normal statistical model used for HRV/RHR — it exists purely to flag a possibly-illness-related change for you to notice. Body temperature does not affect Sleep Score, Load Score, or Readiness in any way. It is a display-only insight, entirely outside the scoring engine.


Workout GPS and Route Details

When outdoor workouts include GPS location tracks, Readylytics visualizes route contours, pace, and elevation profiles directly inside workout details.

Implemented in: RouteSimplifier.kt, RouteDistanceCalculator.kt, RouteContourCard.kt, WorkoutPerformanceCharts.kt, WorkoutDetailScreen.kt


Cardio Fitness (VO2 Max)

Cardio Fitness (VO2 Max) is an indicator of your cardiovascular endurance. The app determines your VO2 Max based on your selected source preference (Auto, Wearable only, Estimate only).

If an estimate is allowed, Readylytics can compute it two ways, selectable in Settings:

Both estimation methods use stable daily baselines and are unavailable until scoring calibration completes.

Your VO2 Max is then benchmarked into five categories (Superior, Excellent, Good, Fair, Poor) based on normative percentiles from the Cooper Institute tailored to your age and sex.


Training Stress Balance (TSB)

Training Stress Balance (TSB) represents your readiness to perform based on your recent training load. It is calculated as TSB = CTL - ATL, where CTL is your Chronic Training Load (42-day average) and ATL is your Acute Training Load (7-day average).

The TSB value places you into one of five zones:

You can view your TSB on the Workouts tab (via a toggle) and optionally enable it as a Dashboard card.


Workout Recommendation

An optional, default-visible Dashboard card that turns this morning’s HRV, last night’s sleep, and your recent training fatigue into one qualitative daily signal: Rest, Easy workout, or Push harder. It reuses the same profile-tuned HRV deviation bounds and illness-detection logic your Readiness score already uses (see Emergency signals, above) — no new coefficients, no separate model.

What decides the recommendation

Missing-data precedence. If we can’t find last night’s sleep at all, or this morning’s HRV reading is missing, we say so directly (“Sleep data missing” / “HRV data missing”) rather than guessing — a missing HRV reading takes priority over any illness signal, since illness detection itself depends on HRV.

Past examples, when guidance is Easy or Push harder. We show up to three of your own past workouts from the preceding 30 days that matched a similar effort level — one per distinct workout type, each longer than 15 minutes, most recent first. Tapping one opens that exact recorded workout. Rest and “no data” days never show examples; if fewer than three workouts qualify, we show fewer.

Existing users. If you already have history, your past days are backfilled with this guidance automatically the next time your local recompute runs — no separate action needed.

Visibility. The card is shown by default and can be hidden from your Dashboard layout at any time, like any other card.

What this is not. There is no generated TRIMP target, workout duration, or heart-rate target attached to this guidance — it is deliberately qualitative, not a number. It is not a “safe,” “optimal,” or validated strength or training prescription, and it is not medical or training advice. It reflects the same recovery-adjacent signals your other scores already use, meant to inform your own judgment, not replace it.

Privacy. Everything above is computed and stored entirely on your device from data you already have locally — no network request is made to produce it. If you use encrypted local backups, your stored recommendations (and the examples they reference) are included like any other computed data. No cloud feature or telemetry was introduced to support this.

Local backup recovery retains verified archives matching the saved password after an interrupted password change. Restore recovery finishes before sync resumes and retains its recovery record until maintenance is released.

Heart-rate history older than 90 days is kept as one-minute summaries rather than individual samples. Each summarised minute now also records which device or app it came from, and that coverage information is included in encrypted local backups so a restore reproduces the same history. Refreshing a source replaces its evidence in these source-backed summaries while preserving other sources; device selection removes discarded sources before rebuilding. Expired summaries, coverage and source evidence are removed together by retention cleanup. Every minute is read from exactly one of the two stores — the raw samples or its summary, never both added together — so a minute can never be counted twice. When a sleep session or workout is later corrected, the summaries it covers are re-derived from that stored per-device record rather than from the previous result, so repeating the correction always lands on the same answer; the only residual difference is that a session boundary falling part-way through a minute can place at most one summarised sample on the wrong side of it. Summaries created before this existed have no per-device record to re-derive from, so they stay marked as approximate and are left exactly as they are — never silently overwritten or presented as corrected. There is currently no way to repair them: “Resync Health Connect data” re-reads your history but does not replace those older summaries, and no other in-app action does either. All of it stays on your device.

Implemented in: ComputeWorkoutRecommendationUseCase.kt, MorningRecommendationAssembler.kt, SelectWorkoutRecommendationExamples.kt


What the app needs from you

We read from Android Health Connect:

The app reads only — it never writes. You can revoke access at any time in Health Connect settings.

If a particular metric is missing on a given day, we’ll either:

Local encryption keys are stored through Android Keystore. On devices that support StrongBox, Readylytics attempts to use StrongBox-backed key protection and falls back to standard Keystore when StrongBox is unavailable. Backup passwords and database keys remain local to the device.


How long until your scores stabilise

Biological baselines take time to learn. We are explicit about the phases:

Progress through these phases depends on the number of nights with usable HRV/RHR data, not calendar age. If you wear your tracker only 3–5 nights a week, the timeline lengthens proportionally.

Implemented in: Phase.kt, PhaseCalculator.kt


A short glossary


Score adjustments you may not see

A few smaller modifiers shape the numbers behind the scenes. We list them here for transparency:

Determinism & timezone

Your scores are computed against a stored scoring timezone, so the same underlying health data and settings always produce the same scores, and scores remain consistent if you travel or change your device’s timezone. Recomputing your history (e.g., after a resync) reproduces identical numbers while the underlying heart-rate samples are still stored raw; once that history has moved to the compact per-minute summary (see Honest limitations), recomputation is a measured, close approximation rather than a bit-identical replay.


Honest limitations

  1. Wearable stage detection is imperfect. Even premium devices misclassify deep and REM sleep on individual nights. We use age-adjusted targets and treat architecture scores as approximate readiness indicators. Architecture differences on individual nights should not be over-interpreted.

  2. Population norms are not destiny. The age-banded deep sleep ranges come from polysomnography studies of healthy adults. Your healthy normal may sit anywhere in your age band. Our scoring uses age-banded targets so the ceiling shifts with you.

  3. Profiles are engineering heuristics, not physics. The cutoffs (Athlete ±20 min, Active ±30 min, Sedentary ±45 min circadian threshold) are chosen for practical usability, not derived from prospective studies. We monitor whether these cutoffs are working well and will adjust if needed.

  4. The ACWR (Readiness load ratio) is descriptive, not predictive. The methodological literature (Lolli et al. 2019; Impellizzeri et al. 2020, 2021) has demonstrated that the acute-to-chronic ratio is often a mathematical artifact and is not a validated causal injury predictor. We approximate Gabbett’s (2016) elevated-risk zone above the 1.3 sweet-spot ceiling with a Gaussian decay penalty — the curve shape is our own modelling choice — and present it strictly as a load-change indicator to help you visualise spikes in training intensity, not as a diagnostic injury-risk score.

  5. One night is noise; trends are signal. Treat any single day’s score as a data point, not a verdict. Look at the 7-day trend.

  6. This app does not diagnose anything. If you suspect sleep apnea, a heart condition, an infection, an injury, or any other health concern, see a clinician. Physiological metrics such as HRV, sleep staging, and resting heart rate are non-specific and can be influenced by numerous behavioral, environmental, pharmacological, and measurement-related factors.

  7. Heart-rate history older than 90 days is stored as a compact per-minute summary (min/max/average plus a five-point percentile sketch) rather than every raw sample. With the same inputs, settings, and storage tier, a historical replay is repeatable in the stored scoring timezone. Heart-rate history that has moved from raw samples to minute summaries is a measured approximation, so raw-to-minute-summary recomputation can differ slightly; replays are repeatable within the same storage tier. Each minute is read from either the raw samples or its summary, never both, so nothing is double-counted; and when a session is corrected the summaries are re-derived from the stored per-device record. Summaries created before that record existed cannot be re-derived at all — they stay marked approximate and are left untouched. No in-app action repairs them today: “Resync Health Connect data” does not replace them, so that part of your history stays approximate.

  8. The Workout Recommendation is not a safe, optimal, or validated training prescription. It is a qualitative Rest/Easy/Push-harder signal derived from the same recovery-adjacent HRV, sleep, and fatigue thresholds used elsewhere in this app — not a strength or endurance program, not a numeric load target, and not medical or training advice. Treat it the same way you would treat any other single-day score: informative, not authoritative.


Selected primary sources informing the scoring: Buysse 1989 (PSQI); Buysse 2014 (RU-SATED); Ohayon et al. 2004, 2017; Hirshkowitz et al. 2015 (NSF); Boulos et al. 2019 (Lancet Respir Med); Lauer et al. 1991; SIESTA database; Plews et al. 2012, 2013, 2014 (HRV monitoring); Buchheit 2014 (Front Physiol); Le Meur et al. 2013 (parasympathetic hyperactivity); Mishra et al. 2020 (Nat Biomed Eng); Quer et al. 2021 (Nat Med); Phillips et al. 2017 (Sleep Regularity Index); Lunsford-Avery et al. 2018; Windred et al. 2023/2024; Khalsa et al. 2003 (phase-response curve); Banister 1991; Foster 1998; Gabbett 2016; Lolli et al. 2019; Impellizzeri et al. 2020/2021.


Scientific and medical disclaimer

This app describes a fitness and training-readiness monitoring framework derived from consumer wearable signals and sports-science literature. The framework is not validated for medical diagnosis, disease screening, treatment guidance, or injury prediction. Profiles and their associated thresholds optimize estimated recovery signals and are engineering heuristics chosen for practical usability, not clinical validation.

If you have concerns about your health, sleep, or recovery, consult a qualified healthcare provider.


Development Transparency

This application was developed with the assistance of AI. While the implementation and scoring logic have been thoroughly reviewed, both AI and human developers can make errors. We encourage community review and welcome issue reports to help improve the application.