Browse Source

Fix low-high estimates

* doc/org.texi (Column attributes): Emphasize estimates format.
  Document degenerate case of plain numbers.
* lisp/org-colview.el (org-columns-compute): Properly sum estimates.
(org-columns-string-to-number): Recognize estimates containing an
unit.
(org-estimate-mean-and-var, org-estimate-print): Allow numbers as
a degenerate case of estimates.

Reported-by: yary <not.com@gmail.com>
<http://permalink.gmane.org/gmane.emacs.orgmode/93505>
Nicolas Goaziou 10 years ago
parent
commit
c1558d34d7
2 changed files with 29 additions and 18 deletions
  1. 7 6
      doc/org.texi
  2. 22 12
      lisp/org-colview.el

+ 7 - 6
doc/org.texi

@@ -5569,7 +5569,7 @@ optional.  The individual parts have the following meaning:
                 @{@@min@}    @r{Minimum age (in days/hours/mins/seconds).}
                 @{@@max@}    @r{Maximum age (in days/hours/mins/seconds).}
                 @{@@mean@}   @r{Arithmetic mean of ages (in days/hours/mins/seconds).}
-                @{est+@}    @r{Add low-high estimates.}
+                @{est+@}    @r{Add @samp{low-high} estimates.}
 @end example
 
 @noindent
@@ -5578,11 +5578,12 @@ include.  Subsequent columns referencing the same property will all display the
 same summary information.
 
 The @code{est+} summary type requires further explanation.  It is used for
-combining estimates, expressed as low-high ranges.  For example, instead
-of estimating a particular task will take 5 days, you might estimate it as
-5--6 days if you're fairly confident you know how much work is required, or
-1--10 days if you don't really know what needs to be done.  Both ranges
-average at 5.5 days, but the first represents a more predictable delivery.
+combining estimates, expressed as @samp{low-high} ranges or plain numbers.
+For example, instead of estimating a particular task will take 5 days, you
+might estimate it as 5--6 days if you're fairly confident you know how much
+work is required, or 1--10 days if you don't really know what needs to be
+done.  Both ranges average at 5.5 days, but the first represents a more
+predictable delivery.
 
 When combining a set of such estimates, simply adding the lows and highs
 produces an unrealistically wide result.  Instead, @code{est+} adds the

+ 22 - 12
lisp/org-colview.el

@@ -952,12 +952,16 @@ display, or in the #+COLUMNS line of the current buffer."
 	      valflag (and val (string-match "\\S-" val)))
 	(cond
 	 ((< level last-level)
-	  ;; put the sum of lower levels here as a property
-	  (setq sum (+ (if (and (/= last-level inminlevel)
-				(aref lvals last-level))
-			   (apply fun (aref lvals last-level)) 0)
-		       (if (aref lvals inminlevel)
-			   (apply fun (aref lvals inminlevel)) 0))
+	  ;; Put the sum of lower levels here as a property.  If
+	  ;; values are estimate, use an appropriate sum function.
+	  (setq sum (funcall
+		     (if (eq fun 'org-estimate-combine) #'org-estimate-combine
+		       #'+)
+		     (if (and (/= last-level inminlevel)
+			      (aref lvals last-level))
+			 (apply fun (aref lvals last-level)) 0)
+		     (if (aref lvals inminlevel)
+			 (apply fun (aref lvals inminlevel)) 0))
 		flag (or (aref lflag last-level) ; any valid entries from children?
 			 (aref lflag inminlevel)) ; or inline tasks?
 		str (org-columns-number-to-string sum format printf)
@@ -1071,6 +1075,9 @@ display, or in the #+COLUMNS line of the current buffer."
           (while l
             (setq sum (+ (string-to-number (pop l)) (/ sum 60))))
           sum))
+       ((memq fmt '(checkbox checkbox-n-of-m checkbox-percent))
+        (if (equal s "[X]") 1. 0.000001))
+       ((memq fmt '(estimate)) (org-string-to-estimate s))
        ((string-match (concat "\\([0-9.]+\\) *\\("
 			      (regexp-opt (mapcar 'car org-effort-durations))
 			      "\\)") s)
@@ -1079,9 +1086,6 @@ display, or in the #+COLUMNS line of the current buffer."
           (while l
             (setq sum (+ (string-to-number (pop l)) (/ sum 60))))
           sum))
-       ((memq fmt '(checkbox checkbox-n-of-m checkbox-percent))
-        (if (equal s "[X]") 1. 0.000001))
-       ((memq fmt '(estimate)) (org-string-to-estimate s))
        (t (string-to-number s)))))
 
 (defun org-columns-uncompile-format (cfmt)
@@ -1509,7 +1513,10 @@ This will add overlays to the date lines, to show the summary for each day."
 
 (defun org-estimate-mean-and-var (v)
   "Return the mean and variance of an estimate."
-  (let* ((low (float (car v)))
+  (let* ((v (cond ((consp v) v)
+		  ((numberp v) (list v v))
+		  (t (error "Invalid estimate type"))))
+	 (low (float (car v)))
          (high (float (cadr v)))
          (mean (/ (+ low high) 2.0))
          (var (/ (+ (expt (- mean low) 2.0) (expt (- high mean) 2.0)) 2.0)))
@@ -1532,8 +1539,11 @@ and variances (respectively) of the individual estimates."
 (defun org-estimate-print (e &optional fmt)
   "Prepare a string representation of an estimate.
 This formats these numbers as two numbers with a \"-\" between them."
-  (if (null fmt) (set 'fmt "%.0f"))
-  (format "%s" (mapconcat (lambda (n) (format fmt n))  e "-")))
+  (let ((fmt (or fmt "%.0f"))
+	(e (cond ((consp e) e)
+		 ((numberp e) (list e e))
+		 (t (error "Invalid estimate type")))))
+    (format "%s" (mapconcat (lambda (n) (format fmt n)) e "-"))))
 
 (defun org-string-to-estimate (s)
   "Convert a string to an estimate.