#!/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