Skip to content

feature request: support habit range for streak calculation #7

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
connormclaud opened this issue Mar 18, 2024 · 1 comment
Open

Comments

@connormclaud
Copy link

connormclaud commented Mar 18, 2024

Current behaviour:
I have weekly review habit:

* TODO Weekly review                     :important:urgent:checklist
SCHEDULED: <2024-03-23 Sat ++7d/8d>

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

Weekly review
Repeats every ++7 days
Current Streak 1

So whenever I mark habit as DONE on Sundays I loose my streak which makes me unhappy.

Desired behavior:

Weekly review
Repeats every ++8 days (ideally every 7)
Current Streak 52
@leafarbelm
Copy link

leafarbelm commented May 26, 2024

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants