Open connormclaud opened 8 months ago
Doing something like this seems to work fine
(defun org-habit-stats-insert-habit-info (habit-data habit-name habit-description)
(let ((habit-repeat-period (nth 1 habit-data))
(habit-deadline-repeater (nth 3 habit-data))
(habit-repeat-string (nth 5 habit-data))
(habit-next-scheduled (nth 0 habit-data)))
(insert (propertize habit-name 'face 'org-habit-stats-habit-name)
"\n")
(if habit-description
(insert habit-description "\n"))
;; insert habit repeat data, next due date
(if habit-deadline-repeater
(insert (format "Repeats every %s%d days (ideally every %s%d days)"
habit-repeat-string habit-deadline-repeater habit-repeat-string habit-repeat-period)
"\n")
(insert (format "Repeats every %s%d days"
habit-repeat-string habit-repeat-period)
"\n"))
(insert (org-habit-stats-format-absolute-time-string "Next Scheduled: %A, %B %d, %Y"
(org-habit-stats-days-to-time habit-next-scheduled))
"\n")))
(defun org-habit-stats--record-streak-full (history _history-rev _habit-data)
"Return (record-streak . record-day).
The record-day is the last day of the record streak. If the
record streak occurs on multiple days, return the earliest one.
See the docstring of `org-habit-stats-streak' for a description
of HISTORY, HISTORY-REV, HABIT-DATA."
(let ((record-streak 0)
(record-day (org-today))
(curr-streak 0)
(curr-streak-start 0)
(deadline-repeater (nth 3 _habit-data)))
(while history
(let* ((next-pair (pop history))
(curr-day (car next-pair))
(curr-completed (cdr next-pair)))
(if (= curr-completed 1)
(progn
(when (= curr-streak 0)
(setq curr-streak-start curr-day))
(if deadline-repeater ;; reset deadline repeater
(setq deadline-repeater (nth 3 _habit-data)))
(setq curr-streak (1+ curr-streak)))
(progn
(if deadline-repeater
(setq deadline-repeater (1- deadline-repeater)))
(if (or (not deadline-repeater) (< deadline-repeater 0))
(setq curr-streak 0))))
(when (> curr-streak record-streak)
(setq record-streak curr-streak)
(setq record-day (+ curr-streak-start curr-streak -1)))))
(cons record-streak record-day)))
(defun org-habit-stats--streak (history habit-data)
(let* ((streak 0)
(deadline-repeater (nth 3 habit-data)))
(while history
(if (= (cdr (pop history)) 1)
(progn
(setq streak (1+ streak))
(if deadline-repeater ;; reset deadline repeater
(setq deadline-repeater (nth 3 habit-data))))
(progn
(if deadline-repeater
(setq deadline-repeater (1- deadline-repeater)))
(if (or (not deadline-repeater) (< deadline-repeater 0))
(setq history '())))
))
streak))
(defun org-habit-stats-streak (_history history-rev _habit-data)
(org-habit-stats--streak history-rev _habit-data))
I don't know much about Elisp, but maybe this could be a starting point. I just rewrote some functions, and there are probably better ways of doing this.
I would love to see something like this implemented.
Current behaviour: I have weekly review habit:
Main idea it will be reviewed over weekend, whatever Saturday or Sunday works fine
But with current implementation of stats module it only aware of habit to be closed every 7 days
So whenever I mark habit as DONE on Sundays I loose my streak which makes me unhappy.
Desired behavior: