Skip to content

Commit 59a8d8a

Browse files
authored
Add autonomic prodrome illness detection (#174)
* Plan autonomic illness prodrome follow-up * Document autonomic prodrome experiments * Add autonomic prodrome illness detection * Address autonomic prodrome review feedback
1 parent b535eae commit 59a8d8a

16 files changed

Lines changed: 1171 additions & 188 deletions

cmd/illness_probe/main.go

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"fmt"
88
"log"
99
"os"
10+
"time"
1011

1112
"health-receiver/internal/health"
1213
"health-receiver/internal/storage"
@@ -16,6 +17,8 @@ func main() {
1617
schema := flag.String("schema", "health", "tenant schema")
1718
lang := flag.String("lang", "en", "briefing language")
1819
date := flag.String("date", "", "specific local date YYYY-MM-DD; defaults to latest briefing")
20+
from := flag.String("from", "", "start local date YYYY-MM-DD for inclusive sweep")
21+
to := flag.String("to", "", "end local date YYYY-MM-DD for inclusive sweep")
1922
days := flag.Int("days", 0, "retrospective sweep over recent daily_scores dates")
2023
noCheckin := flag.Bool("no-checkin", false, "ignore subjective check-in evidence")
2124
flag.Parse()
@@ -31,6 +34,11 @@ func main() {
3134
return
3235
}
3336

37+
if *from != "" || *to != "" {
38+
runRange(db, *schema, *from, *to, !*noCheckin)
39+
return
40+
}
41+
3442
if *date != "" {
3543
printDate(db, *schema, *date, !*noCheckin)
3644
return
@@ -111,6 +119,55 @@ func runSweep(db *storage.DB, schema string, days int, includeCheckin bool) {
111119
printJSON(map[string]any{"schema": schema, "days": days, "counts": counts, "top_hits": hits})
112120
}
113121

122+
func runRange(db *storage.DB, schema, from, to string, includeCheckin bool) {
123+
if from == "" || to == "" {
124+
log.Fatal("--from and --to must be provided together")
125+
}
126+
if _, err := time.Parse("2006-01-02", from); err != nil {
127+
log.Fatalf("invalid --from date: %v", err)
128+
}
129+
if _, err := time.Parse("2006-01-02", to); err != nil {
130+
log.Fatalf("invalid --to date: %v", err)
131+
}
132+
rows, err := db.QueryReadOnly("SELECT date FROM daily_scores WHERE date >= $1 AND date <= $2 ORDER BY date", from, to)
133+
if err != nil {
134+
log.Fatal(err)
135+
}
136+
type day struct {
137+
Date string `json:"date"`
138+
Confidence string `json:"confidence"`
139+
Pattern string `json:"pattern,omitempty"`
140+
Signals []string `json:"signals,omitempty"`
141+
}
142+
out := struct {
143+
Schema string `json:"schema"`
144+
From string `json:"from"`
145+
To string `json:"to"`
146+
Counts map[string]int `json:"counts"`
147+
Days []day `json:"days"`
148+
}{Schema: schema, From: from, To: to, Counts: map[string]int{"none": 0, "low": 0, "moderate": 0, "high": 0}}
149+
for _, row := range rows {
150+
date, _ := row["date"].(string)
151+
if date == "" {
152+
continue
153+
}
154+
var checkin *health.SubjectiveCheckinSummary
155+
if includeCheckin {
156+
checkin = checkinForDate(db, date)
157+
}
158+
ill := health.ComputeIllnessSuspicion(db.BuildIllnessEvidenceInput(date, checkin))
159+
out.Counts[ill.Confidence]++
160+
d := day{Date: date, Confidence: ill.Confidence, Pattern: ill.Pattern}
161+
for _, sig := range ill.Signals {
162+
if sig.Status == "ok" && sig.Strength != "weak" && (sig.Contributes || sig.Metric == "sustained_hr_load") {
163+
d.Signals = append(d.Signals, sig.Metric+":"+sig.Strength)
164+
}
165+
}
166+
out.Days = append(out.Days, d)
167+
}
168+
printJSON(out)
169+
}
170+
114171
func checkinForDate(db *storage.DB, date string) *health.SubjectiveCheckinSummary {
115172
row, err := db.GetTodayCheckin(date, storage.CheckinSourceTelegram)
116173
if err != nil || row == nil {

0 commit comments

Comments
 (0)