aboutsummaryrefslogtreecommitdiff
path: root/docs/design/stats-dashboard.org
diff options
context:
space:
mode:
Diffstat (limited to 'docs/design/stats-dashboard.org')
-rw-r--r--docs/design/stats-dashboard.org118
1 files changed, 77 insertions, 41 deletions
diff --git a/docs/design/stats-dashboard.org b/docs/design/stats-dashboard.org
index 6bb18d9..ba01ae3 100644
--- a/docs/design/stats-dashboard.org
+++ b/docs/design/stats-dashboard.org
@@ -24,17 +24,26 @@ what each card carries in its own =DRILL_*= properties.
The currently-retained per-card data is real and usable:
-| Property | Source |
-|----------+--------|
-| =DRILL_LAST_INTERVAL= | scheduler output, updated every review |
-| =DRILL_REPEATS_SINCE_FAIL= | review counter resetting on a lapse |
-| =DRILL_TOTAL_REPEATS= | lifetime review count for the card |
-| =DRILL_FAILURE_COUNT= | lifetime lapses |
-| =DRILL_AVERAGE_QUALITY= | running mean of the 0–5 quality scale |
-| =DRILL_EASE= | SM-family easiness factor |
-| =DRILL_LAST_QUALITY= | quality at the most recent review |
-| =DRILL_LAST_REVIEWED= | inactive timestamp of the most recent review |
-| =DATE_ADDED= | inactive timestamp of card creation |
+| Property | Source |
+|----------------------------+----------------------------------------------|
+| =DRILL_LAST_INTERVAL= | scheduler output, updated every review |
+|----------------------------+----------------------------------------------|
+| =DRILL_REPEATS_SINCE_FAIL= | review counter resetting on a lapse |
+|----------------------------+----------------------------------------------|
+| =DRILL_TOTAL_REPEATS= | lifetime review count for the card |
+|----------------------------+----------------------------------------------|
+| =DRILL_FAILURE_COUNT= | lifetime lapses |
+|----------------------------+----------------------------------------------|
+| =DRILL_AVERAGE_QUALITY= | running mean of the 0–5 quality scale |
+|----------------------------+----------------------------------------------|
+| =DRILL_EASE= | SM-family easiness factor |
+|----------------------------+----------------------------------------------|
+| =DRILL_LAST_QUALITY= | quality at the most recent review |
+|----------------------------+----------------------------------------------|
+| =DRILL_LAST_REVIEWED= | inactive timestamp of the most recent review |
+|----------------------------+----------------------------------------------|
+| =DATE_ADDED= | inactive timestamp of card creation |
+|----------------------------+----------------------------------------------|
What's missing is the *temporal axis*: there's no record that the user
reviewed N cards on a given day, or that the pass percentage trended
@@ -116,18 +125,28 @@ Each entry is an `org-drill-session-record' struct.")
=org-drill-session-record= is a =cl-defstruct=:
-| Slot | Type | Meaning |
-|------+------+---------|
-| =start-time= | float | =float-time= at session start |
-| =end-time= | float | =float-time= at session end |
-| =scope= | symbol or list | =org-drill-scope= value at session start |
-| =algorithm= | symbol | =org-drill-spaced-repetition-algorithm= at start |
-| =qualities= | vector of int | every quality 0–5 entered, in order |
-| =pass-percent= | int | qualities > =org-drill-failure-quality=, / total |
-| =new-count= | int | size of =(oref session new-entries)= at end |
-| =mature-count= | int | =young-mature= + =old-mature= entries at end |
-| =failed-count= | int | =failed-entries= at end |
-| =cram-mode= | bool | =cram-mode= at session start |
+| Slot | Type | Meaning |
+|----------------+----------------+--------------------------------------------------|
+| =start-time= | float | =float-time= at session start |
+|----------------+----------------+--------------------------------------------------|
+| =end-time= | float | =float-time= at session end |
+|----------------+----------------+--------------------------------------------------|
+| =scope= | symbol or list | =org-drill-scope= value at session start |
+|----------------+----------------+--------------------------------------------------|
+| =algorithm= | symbol | =org-drill-spaced-repetition-algorithm= at start |
+|----------------+----------------+--------------------------------------------------|
+| =qualities= | vector of int | every quality 0–5 entered, in order |
+|----------------+----------------+--------------------------------------------------|
+| =pass-percent= | int | qualities > =org-drill-failure-quality=, / total |
+|----------------+----------------+--------------------------------------------------|
+| =new-count= | int | size of =(oref session new-entries)= at end |
+|----------------+----------------+--------------------------------------------------|
+| =mature-count= | int | =young-mature= + =old-mature= entries at end |
+|----------------+----------------+--------------------------------------------------|
+| =failed-count= | int | =failed-entries= at end |
+|----------------+----------------+--------------------------------------------------|
+| =cram-mode= | bool | =cram-mode= at session start |
+|----------------+----------------+--------------------------------------------------|
A single record is small (a few hundred bytes). At one session per
day, the log holds a year of history in well under 100 KB. At three
@@ -275,12 +294,19 @@ helper. Users who want TSV can run a one-line sed pipe.
The expensive paths and their bounds:
-| Path | Cost | Mitigation |
-|------+------+------------|
-| Session log save | one =persist-save= per session | already wrapped in =condition-case=; cost is a few KB write |
-| Scope walk on dashboard open | =org-map-entries= over scope | same cost as a session open; cached for the dashboard's lifetime, refreshes on =g= |
-| CSV export | one walk + one file write | one-off; user-triggered |
-| Sparkline rendering | bucket the in-memory log by day | log is bounded; bucket-by-day is linear in log length |
+| Path | Cost | Mitigation |
+|------------------------------+---------------------------------+-----------------------------------------------------|
+| Session log save | one =persist-save= per session | already wrapped in =condition-case=; cost is a few |
+| | | KB write |
+|------------------------------+---------------------------------+-----------------------------------------------------|
+| Scope walk on dashboard open | =org-map-entries= over scope | same cost as a session open; cached for the |
+| | | dashboard's lifetime, refreshes on =g= |
+|------------------------------+---------------------------------+-----------------------------------------------------|
+| CSV export | one walk + one file write | one-off; user-triggered |
+|------------------------------+---------------------------------+-----------------------------------------------------|
+| Sparkline rendering | bucket the in-memory log by day | log is bounded; bucket-by-day is linear in log |
+| | | length |
+|------------------------------+---------------------------------+-----------------------------------------------------|
The dashboard does *not* run at session open or close — only when the
user invokes =M-x org-drill-statistics=. Session-end pays one =persist-save=
@@ -393,18 +419,28 @@ the export + docs + polish.
All 10 open questions resolved as recommended. Implementation can
proceed against this spec.
-| # | Question | Resolution |
-|---+----------+------------|
-| 1 | Persistence shape | =persist-defvar=, mirroring the SM5 matrix |
-| 2 | Corrupted-load recovery | warn, fresh-start, rename to =.corrupt-YYYY-MM-DD= |
-| 3 | Sparkline character set | quadrant blocks (▁▂▃▄▅▆▇█) |
-| 4 | Filter scope | single buffer-wide filter |
-| 5 | CSV delimiter | =,= with proper quoting |
-| 6 | Dashboard-open mode | sync |
-| 7 | Aborted-session recording | record nothing; =unwind-protect= deferred |
-| 8 | Dashboard keymap | =q g e s r a RET= |
-| 9 | Leech-quality threshold default | 2.5 |
-| 10 | Defcustom group placement | sibling group =org-drill-statistics= |
+| # | Question | Resolution |
+|----+---------------------------------+----------------------------------------------------|
+| 1 | Persistence shape | =persist-defvar=, mirroring the SM5 matrix |
+|----+---------------------------------+----------------------------------------------------|
+| 2 | Corrupted-load recovery | warn, fresh-start, rename to =.corrupt-YYYY-MM-DD= |
+|----+---------------------------------+----------------------------------------------------|
+| 3 | Sparkline character set | quadrant blocks (▁▂▃▄▅▆▇█) |
+|----+---------------------------------+----------------------------------------------------|
+| 4 | Filter scope | single buffer-wide filter |
+|----+---------------------------------+----------------------------------------------------|
+| 5 | CSV delimiter | =,= with proper quoting |
+|----+---------------------------------+----------------------------------------------------|
+| 6 | Dashboard-open mode | sync |
+|----+---------------------------------+----------------------------------------------------|
+| 7 | Aborted-session recording | record nothing; =unwind-protect= deferred |
+|----+---------------------------------+----------------------------------------------------|
+| 8 | Dashboard keymap | =q g e s r a RET= |
+|----+---------------------------------+----------------------------------------------------|
+| 9 | Leech-quality threshold default | 2.5 |
+|----+---------------------------------+----------------------------------------------------|
+| 10 | Defcustom group placement | sibling group =org-drill-statistics= |
+|----+---------------------------------+----------------------------------------------------|
* References