123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174 |
- #!/bin/bash
- set -o nounset
- set -o errexit
-
- function _echo
- {
- echo -e "$1"
- }
-
- function _echoB
- {
- _echo "\033[1m$1\033[0m"
- }
-
- red=$(tput setaf 1)
- green=$(tput setaf 2)
- yellow=$(tput setaf 3)
- normal=$(tput sgr0)
-
- function _help
- {
- _echo ""
- _echoB "A command line PERT calculator for quick estimates."
- _echo "Comma separated task list in the form \"one,1,2,12 two,4,5,9 three,2,3,6\", where whitespace separates tasks."
- _echo ""
- _echoB "Usage:"
- _echo "\tpert [name,optimistic,realistic,pessimistic]"
- _echo ""
- _echoB "Example:"
- _echo "\tpert one,1,3,4"
- _echo "\tpert one,10,15,20 two,5,7,10"
- _echo "\tpert \"one,1,2,3\" \"two,15,17,20\""
- _echo ""
- }
-
- scale=2
- function _calc
- {
- _echo "scale=$scale; $@" | bc -l | sed 's/^\./0./'
- }
-
- width=88
- function _divider
- {
- divider=------------------------------
- divider=" +"$divider$divider$divider"+"
- printf "%$width.${width}s+\n" "$divider"
- }
-
- readonly format=" | %-12s |${green}%11s${normal} |%10s |${red}%12s${normal} |%9s |${yellow}%9s${normal} |%9s |\n"
- function _header
- {
- _echo ""
- _echoB "Task"
- _echo ""
- _divider
- printf "$format" "#" "optimistic" "realistic" "pessimistic" "duration" "risk" "variance"
- _divider
- }
-
-
- function pert_table
- {
- _header
-
- counter=0
- total_estimate=0
- total_standard_deviation=0
- total_variance=0
- time=("$@")
- for var in "${time[@]}"; do
-
- # counter iterator
- counter=$[$counter +1]
-
- # split values
- IFS=',' read -ra ADDR <<< "$var"
- o="0"
- if [ -n "${ADDR[0]-}" ]; then
- t=${ADDR[0]}
- fi
-
- # optimistic value
- o="0"
- if [ -n "${ADDR[1]-}" ]; then
- o=${ADDR[1]}
- fi
-
- # realistic value
- r="0"
- if [ -n "${ADDR[2]-}" ]; then
- r=${ADDR[2]}
- fi
-
- # pessimistic value
- p="0"
- if [ -n "${ADDR[3]-}" ]; then
- p=${ADDR[3]}
- fi
-
- # check values
- if [ -z "$o" ] || [ -z "$r" ] || [ -z "$p" ]; then
- printf "$format" "$counter. bad input" $t $o $r $p
- else
-
- # pert estimate
- pert_estimate=$(_calc "($o+4*$r+$p)/6")
- total_estimate=$(_calc "$total_estimate + $pert_estimate")
-
- # standard deviation
- standard_deviation=$(_calc "($p-$o)/6")
- total_standard_deviation=$(_calc "$total_standard_deviation + $standard_deviation")
-
- # variance
- variance=$(_calc "$standard_deviation * $standard_deviation")
- total_variance=$(_calc "$total_variance + $variance")
-
- # row
- printf "$format" "$counter."$t $o $r $p $pert_estimate $standard_deviation $variance
- fi
-
- done
-
- _divider
-
- if [[ $total_estimate > 0 ]]; then
-
- # footer summary
- printf "$format" "summary" "-" "-" "-" $total_estimate $total_standard_deviation $total_variance
- _divider
-
- _echo ""
- _echoB "Three point estimates"
- _echo ""
-
- width=42
- tpeformat=" | %-13s |%11s |%10s |\n"
-
- _divider
- printf "$tpeformat" "confidence"
- _divider
- printf "$tpeformat" "1 Sigma - 68%" $(_calc "$total_estimate - $total_standard_deviation") $(_calc "$total_estimate + $total_standard_deviation")
- printf "$tpeformat" "2 Sigma - 95%" $(_calc "$total_estimate - 2 * $total_standard_deviation") $(_calc "$total_estimate + 2 * $total_standard_deviation")
- printf "$tpeformat" "3 Sigma - 99%" $(_calc "$total_estimate - 3 * $total_standard_deviation") $(_calc "$total_estimate + 3 * $total_standard_deviation")
- _divider
-
- fi
-
- _echo ""
- }
-
-
- # main
- if [ ! -t 0 ];then
- time=$(cat -)
- pert_table ${time[@]}
- else
- if [ $# -eq 0 ]; then
- _help
- exit 1
- fi
-
- case "$1" in
- *help|*h)
- _help
- exit 1
- ;;
- *)
-
- pert_table $@
- exit 0
- ;;
- esac
- fi
|