ENH remove time-dependent code from status functions

This commit is contained in:
Nathan Dwarshuis 2022-03-13 12:10:37 -04:00
parent 3349190dd3
commit 889520d2bf
1 changed files with 81 additions and 134 deletions

View File

@ -1760,24 +1760,8 @@ return another status."
(cons ,node-form))))
(defun org-x-dag-id->action-status (id in-iteratorp)
(cl-flet*
((to-valid-closed
(id type ts)
(->> (if (->> (org-ml-timestamp-get-start-time ts)
(org-ml-time-to-unixtime)
(org-x-dag-time-is-archivable-p))
:archivable
:complete)
(org-x-dag-action-status id type)))
(check-archivable
(id closed status)
(org-x-dag-status-with-data status
(-let (((&plist :code c :action-type a) it-data))
(if (eq c :archivable)
(to-valid-closed id a closed)
(org-x-dag-action-status id a c)))))
(iterator-status
(cl-flet
((iterator-status
(id kw closed c-statuses)
(cond
((not (org-x-dag-id->node-property "ARCHIVE" id))
@ -1786,30 +1770,24 @@ return another status."
(->> (format "Iterator must have %s set" org-x-prop-time-shift)
(org-x-dag-status-error id)))
((equal kw org-x-done-keywords)
(->>
(org-x-dag-id->with-action-child-statuses id c-statuses :iterator
((:valid :archivable)
(:valid :complete)
((:valid :complete)
(:error "Complete iterators can only have complete child nodes"))
(lambda (_ type code)
(when (memq type '(:iterator-task :iterator-project))
(pcase code
(:archivable 0)
(:complete 1)
((or :active :future) 2))))
(org-x-dag-action-status id :iterator :complete))
(check-archivable id closed)))
(:complete 0)
(:active 1))))
(org-x-dag-action-status id :iterator :complete)))
((equal kw org-x-kw-todo)
(org-x-dag-id->with-action-child-statuses id c-statuses :iterator
((:valid :empty)
(:valid :active)
(:valid :future))
(:valid :active))
(lambda (_ type code)
(when (memq type '(:iterator-task :iterator-project))
(pcase code
((or :archivable :complete) 0)
(:active 1)
(:future 2))))
(:complete 0)
(:active 1))))
(org-x-dag-action-status id :iterator :empty)))
(t
(funcall to-error "Iterator can only have DONE/CANC/TODO keywords"))))
@ -1818,36 +1796,27 @@ return another status."
(id kw closed c-statuses)
(cond
((equal kw org-x-kw-done)
(->>
(org-x-dag-id->with-action-child-statuses id c-statuses :iterator-project
((:valid :archivable)
(:valid :complete)
((:valid :complete)
(:error "Complete iterator projects can only have complete children"))
(lambda (_ type code)
(when (memq type '(:iterator-task :iterator-project))
(pcase code
(:archivable 0)
(:complete 1)
((or :active :future) 2))))
(to-valid-closed id :iterator-task closed))
(check-archivable id closed)))
(:complete 0)
(:active 1))))
(org-x-dag-action-status id :iterator-task :complete)))
((equal kw org-x-kw-todo)
(org-x-dag-id->with-action-child-statuses id c-statuses :iterator-project
((:error "Open iterator projects must have at least one active child")
(:valid :active)
(:valid :future))
(:valid :active))
(lambda (_ type code)
(when (memq type '(:iterator-project :iterator-task))
(pcase code
((or :archivable :complete) 0)
(:active 1)
(:future 2))))
(-if-let (ts (or (org-x-dag-id->planning-epoch :scheduled id)
(org-x-dag-id->planning-epoch :deadline id)))
(let ((code (if (< org-x-iterator-active-future-offset
(- ts (float-time)))
:future :active)))
(org-x-dag-action-status id :iterator-task code))
(:complete 0)
(:active 1))))
(if (or (org-x-dag-id->planning-epoch :scheduled id)
(org-x-dag-id->planning-epoch :deadline id))
(org-x-dag-action-status id :iterator-task :active)
(->> "Iterator tasks must be scheduled or deadlined"
(org-x-dag-status-error id)))))
(t
@ -1860,19 +1829,17 @@ return another status."
((equal kw org-x-kw-done)
(->>
(org-x-dag-id->with-action-child-statuses id c-statuses :project
((:valid :archivable)
(:valid :complete)
((:valid :complete)
(:error "DONE projects can only have complete child nodes"))
;; TODO figure out what to do when a key doesn't match, it
;; should make an error but not sure if it should be a
;; runtime error or a returned status error
(lambda (_ type code)
(pcase `(,type ,code)
(`(,_ :archivable) 0)
(`(,_ :complete) 1)
(`(:project ,(or :stuck :held :wait :active)) 2)
(`(:task :active) 2)
(`(:iterator ,(or :active :future :empty) 2))
(`(,_ :complete) 0)
(`(:project ,(or :stuck :held :wait :active)) 1)
(`(:task :active) 1)
(`(:iterator ,(or :active :future :empty) 1))
(e (error "Invalid task/code combination: %S" e))))
(to-valid-closed id :task closed))
(check-archivable id closed)))
@ -1885,7 +1852,7 @@ return another status."
(:valid :active))
(lambda (id type code)
(pcase `(,type ,code)
(`(,_ ,(or :archivable :complete)) 0)
(`(,_ :complete) 0)
(`(:project :stuck) 1)
(`(:project :held) 2)
(`(:project :wait) 3)
@ -1897,12 +1864,11 @@ return another status."
((equal kw org-x-kw-wait) 3)
((equal kw org-x-kw-next) 4)
((equal kw org-x-kw-todo)
(if (org-x-dag-id->planning-timestamp :scheduled id)
4 1))
(if (org-x-dag-id->planning-timestamp :scheduled id) 4 1))
(t
(error "Could not translate task with keyword: %s" kw)))))
(`(:iterator ,(or :active :empty)) 1)
(`(:iterator :future) 4)
(`(:iterator :empty) 1)
(`(:iterator :active) 4)
(e (error "Invalid task/code combination: %S" e))))
(org-x-dag-action-status id :task :active)))
(t
@ -1938,11 +1904,7 @@ return another status."
"Iterators cannot be nested")))
(org-x-dag-status-error id general-error)
(cond
;; CANC actions work the same regardless of action type; if the
;; closed timestamp is archivable, its :archivable, otherwise it is
;; :complete (NOTE that this is 'nice' because I made it such that
;; :complete and :archivable have the same meaning and key for all
;; action types)
;; CANC actions work the same regardless of action type
((equal kw org-x-kw-canc)
(let ((type (cond
(iteratorp :iterator)
@ -1950,7 +1912,7 @@ return another status."
(if it :iterator-project :iterator-task))
(t
(if it :project :task)))))
(to-valid-closed id type closed)))
(org-x-dag-action-status id type :complete)))
;; assuming none of the general checks above matched, try more
;; specific checks depending on if the current action is an iterator
;; (and if we are inside one)
@ -1961,10 +1923,6 @@ return another status."
(t
(project-status id kw closed it))))))))
(defun org-x-dag-id->has-done-error-p (id)
(or (and (not (org-x-dag-id->is-done-p id)) (org-x-dag-id->is-closed-p id))
(and (org-x-dag-id->is-done-p id) (not (org-x-dag-id->is-closed-p id)))))
(defun org-x-dag-status-check-todo-or-done (id to-error alt-fun)
(declare (indent 2))
(org-x-dag-status-check-done id kw to-error
@ -1986,21 +1944,12 @@ return another status."
"DONE/CANC nodes must have closed timestamp")))
(defun org-x-dag-id->created-error (id)
(unless (org-x-dag-id->created-in-past-p id)
"Node must have creation timestamp in the past"))
(unless (org-x-dag-id->node-property org-x-prop-created id)
"Node must have creation timestamp"))
;; TODO it might make more sense to make a 'status' independent of time, such
;; that as time changes, we don't need to constantly recalculate this
(defun org-x-dag-id->endpoint-status (id)
(cl-flet*
((to-valid-closed
(id ts)
(->> (if (->> (org-ml-timestamp-get-start-time ts)
(org-ml-time-to-unixtime)
(org-x-dag-time-is-archivable-p))
:archivable
:complete)
(org-x-dag-endpoint-status id nil))))
(let ((kw (org-x-dag-id->todo id))
(closed (org-x-dag-id->planning-timestamp :closed id)))
(org-x-dag-id->with-nested-buffer-children id
@ -2016,19 +1965,17 @@ return another status."
"Endpoint goal has invalid keyword: %s" kw))))
(org-x-dag-status-error id general-error)
(if (equal kw org-x-kw-canc)
(to-valid-closed id closed)
(org-x-dag-endpoint-status id nil :complete)
(let ((deadline (org-x-dag-id->planning-epoch :deadline id)))
(if (equal kw org-x-kw-done)
(org-x-dag-id->with-endpoint-child-statuses id it deadline
((:valid :archivable)
(:valid :complete)
((:valid :complete)
(:error "Closed endpoint goals must only have closed children"))
(lambda (_ _ _ code)
(pcase code
(:archivable 0)
(:complete 1)
(:active 2)))
(to-valid-closed id closed))
(:complete 0)
(:active 1)))
(org-x-dag-endpoint-status id nil :complete))
(org-x-dag-id->with-endpoint-child-statuses id it deadline
((:error "Open endpoint goals must have at least one open child")
(:valid :active)
@ -2039,8 +1986,8 @@ return another status."
2
(pcase code
(:active 1)
((or :complete :archivable) 2))))
(org-x-dag-endpoint-status id deadline :active))))))))))
(:complete 2))))
(org-x-dag-endpoint-status id deadline :active)))))))))
(defun org-x-dag-toplevel-goal-status (id)
(org-x-dag-status-valid id :toplevel-goal))