From ec5076f93678a3ca5d0944cd777a0d87c74dfeee Mon Sep 17 00:00:00 2001 From: Martin Becker Date: Thu, 2 May 2013 23:08:40 +0200 Subject: [PATCH] contrib/lisp/ox-taskjuggler.el: Smart inference of task progress when exporting to TJ3 * contrib/lisp/ox-taskjuggler.el: Extend variable `complete' to respect clock times if no other information is given. There are three possibilities for setting a task's progress when exporting to TJ3: 1) If TODO state equals "done" => 100% 2) If property "complete" is explicitly given => use that. 3) Otherwise get the clocksum of the task and set the progress by comparing to `effort'. --- contrib/lisp/ox-taskjuggler.el | 36 ++++++++++++++++++++++++++++++++---- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/contrib/lisp/ox-taskjuggler.el b/contrib/lisp/ox-taskjuggler.el index 3458e06..97c4aae 100644 --- a/contrib/lisp/ox-taskjuggler.el +++ b/contrib/lisp/ox-taskjuggler.el @@ -780,6 +780,17 @@ channel." ;; Closing report. "}\n")) + +(defun org-taskjuggler--clocksum-task (task) + "Return the clocksum of a parsed subtree => does not verify +whether the parsed duration matches the start and end times" + (let* ((tsum 0)) + (org-element-map (org-element-contents task) 'clock + (lambda (hl) (setq tsum (+ tsum (org-duration-string-to-minutes + (org-element-property :duration hl)))))) + tsum + )) + (defun org-taskjuggler--build-task (task info) "Return a task declaration. @@ -791,11 +802,28 @@ a property \"task_id\" it will be used as the id for this task. Otherwise it will use the ID property. If neither is defined a unique id will be associated to it." (let* ((allocate (org-element-property :ALLOCATE task)) + (effort (org-element-property :EFFORT task)) + ;; smart completeness inference: + ;; - if state=done => 100% + ;; - if explicit property for "complete" => take that value + ;; - otherwise get clocksum of this task and relate to the + ;; effort, whilst limiting values to [0,99] + ;; => 100% possible if and only if state=DONE. + ;; Overbooking does stop at 99%. + (complete-explicit (org-element-property :COMPLETE task)) (complete - (if (eq (org-element-property :todo-type task) 'done) "100" - (org-element-property :COMPLETE task))) + ;; state=done => complete=100 + (if (eq (org-element-property :todo-type task) 'done) 100.0 + ;; else if explicit property => use that + (if complete-explicit (string-to-number complete-explicit) + ;; else guess the completeness from clocksum + (let* ((clocked (org-taskjuggler--clocksum-task task)) + (complete-guess + (and effort (/ (* 100 clocked) + (org-duration-string-to-minutes effort))))) + (and complete-guess (max (min 99 complete-guess) 0))) + ))) (depends (org-taskjuggler-resolve-dependencies task info)) - (effort (org-element-property :EFFORT task)) (milestone (or (org-element-property :MILESTONE task) (not (or (org-element-map (org-element-contents task) 'headline @@ -826,7 +854,7 @@ a unique id will be associated to it." (if (>= org-taskjuggler-target-version 3.0) "allocate" "allocations") allocate)) - (and complete (format " complete %s\n" complete)) + (and complete (format " complete %.1f\n" complete)) (and effort (format " effort %s\n" (let* ((minutes (org-duration-string-to-minutes effort)) -- 1.7.9.5