Calculate the performance of employee

Hi Guys,

I need to determine the employee performance and calculate their salaries based on each quarter

Expected output

enter the no. of Employee  2
2
Enter Employee Name sam
Enter salary 1000
Enter Q1 5
Enter Q2 6
Enter Q3 3
Enter Q4 5
Enter Employee Name anderson
Enter salary 5000
Enter Q1 7
Enter Q2 7
Enter Q3 8
Enter Q4 8
EMPNAME | SALARY | Q1 | Q2 | Q3 | Q4 | Avg Q | Expected Sal | Incremented Sal | Performance |
sam 1000 5 6 3 5 4.0 1040.0 40.0 ON TRACK
anderson 5000 7 7 8 8 7.0 5350.0 350.0 BEST

code in python

def avg_check(q1,q2,q3,q4) :
    sum = q1 + q2 + q3 + q4
    av1 = float(sum / 4)
    return av1
def check_desc(av1) :
    if av1 >= 7 :
           desc="BEST"
    elif av1 <=7 and av1 >=5 :
           desc="AVG"
    else:
           desc="ON TRACK"
    return desc
details=[ ]
n=input("enter the no. of Employee  ")
print n
for i in range(n):
        name=raw_input("Enter Employee Name ")
        salary=input("Enter salary ")
        q1=input("Enter Q1 ")
        q2=input("Enter Q2 ")
        q3=input("Enter Q3 ")
        q4=input("Enter Q4 ")
        av=avg_check(q1,q2,q3,q4)
        inc_salary=float(salary * av / 100)
        exp_salary=float(salary + inc_salary)
        desc=check_desc(av)
        emp=[name,salary,q1,q2,q3,q4,av,exp_salary,inc_salary,desc]
        details.append(emp)
final=sorted(details, key = lambda x: int(x[6]))
print "EMPNAME | SALARY | Q1 | Q2 | Q3 | Q4 | Avg Q | Expected Sal | Incremented Sal | Performance | "
for i in range(len(final)):
    print " ".join(map(str,final)) 

Can this be done on shell scripting in efficient way with good formatting of header and column

Hi rohit_shinez:

IMHO I don't think you will be able to better Python for your use here, of which your version is 2.x.x.
It might be a better bet to translate to Python 3.x.x, (currently 3.7.x stable).

Apart from Awk, inline floating point arithmetic is not quickly and easily possible without external utilities, such as Python, Perl, bc, etc, using most UNIX shells.
And even the shells that have FP, (ksh and zsh for example), make for shell lock-in, so portability is not at all easy.

Having written that, so long as the utilities are available in all users cases then a POSIX version might be translatable from your code...

/Me thinks I will have a go...

As the python code already exists, it'd be most efficient to just tweak it so the formatting is exactly what you want.

Aside: the av1 <= 7 will never be reached with av1 equals 7 as that is already taken one statement above. This comment may look like nit-picking, but in coding you should always know exactly what you are doing.

Thanks Guys for your comments, I would like to know whether in unix bash script this can be done in efficient way. Can you guys help

Hi rohit_shinez...
(Apologies for any typos.)
In bash? Hmm, awk - most probably as it has builtin scientific maths and floating point capability, but I am no expert.
Bash has ONLY integer maths and that is its limitation. As I quoted before if you have access to tools/utilities that can do floats, Python, Perl, bc, dc, or others then it is possible as is creating your own FIXED point maths calculator. (Note: 'maths' as I am UKan.)
A simple fully POSIX compliant example of making a floating point number divided by an integer like your case. All values are global here to make for an easy to understand to the problems involved if you don't have any decent tools to manipulate scientific and FP values.
Also POSIX does NOT allow x**y hence the multiplier function. Fortunately 'bash' CAN handle this in integer mode only but not shown:

#!/usr/local/bin/dash

NUMBER=0
M=0
N=0
MULTIPLIER=1
TIMES_TEN=10
POWER=1
NO_DECIMAL=1

remove_decimal_point()
{
    NUMBER=$1
    M=${NUMBER%.*}
    N=${NUMBER#*.}
    MULTIPLIER=${#N}
    NO_DECIMAL=${M}${N}
}

multiplier()
{
    TIMES_TEN=$1
    POWER=1
    while [ ${TIMES_TEN} -ge 1 ]
    do
        POWER=$(( POWER * 10 ))
        TIMES_TEN=$(( TIMES_TEN - 1 ))
    done
}

remove_decimal_point 321.12345678

multiplier ${MULTIPLIER}

echo "Variables as global for this demo..."
echo "${NUMBER}"
echo "${M}"
echo "${N}"
echo "${NO_DECIMAL}"
echo "${MULTIPLIER}"
echo "${TIMES_TEN}"
echo ""
echo "Two calculations..."
echo "Firstly: Convert back to original string..."
printf "%.8f\n" "$(( NO_DECIMAL ))e-${MULTIPLIER}"
echo "Secondly: Two integers being divided and converted to FLOAT string..."
printf "%.8f\n" "$(( NO_DECIMAL / 11 ))e-${MULTIPLIER}"
echo "Confirm using Python..."
python -c "print( 321.12345678 / 11 )"

Result for this maths dilemma: OSX 10.14.3, default bash terminal calling dash...

Last login: Thu Aug  8 16:51:21 on ttys000
AMIGA:amiga~> cd Desktop/Code/Shell
AMIGA:amiga~/Desktop/Code/Shell> ./Float_Test.sh
Variables as global for this demo...
321.12345678
321
12345678
32112345678
8
0

Two calculations...
Firstly: Convert back to original string...
321.12345678
Secondly: Two integers being divided and converted to FLOAT string...
29.19304152
Confirm using Python...
29.1930415255
AMIGA:amiga~/Desktop/Code/Shell> _

You now see your problem...
HOWEVER; as I also quoted 'ksh' supports floating point arithmetic, including, float**another_float , which I have used often...
Unless your system does NOT have Python support then the code you have already would probably be better suited translated to awk.
I will pass those thoughts on to our awk experts...
I hope this helps wrap things up...

Thanks for your inputs, I am mainly looking for the same program to work on unix bash script. Can you able to help how i can achieve it instead of python code

This is the correct approach as RudiC has pointed out.

Agree to that, But would more keen on bash scripting for learning purpose

I have already stated that bash ONLY has integer maths, so let's see its limitations:

q1=6; q2=7; q3=5; q4=7
av1=$(( (q1+q2+q3+q4)/4 ))
echo "$av1"
# Gives the result 6. WRONG! The REAL answer is 6.25.

(<CR> is the ENTER key.)
Try this example in bash: echo $(( 3/4 ))<CR> and see the result as 0, ZERO, NOT 0.75!
Now try this in bash: NUM=$(( 3/4 )); if [ "${NUM}" -le "0.75" ]; then echo "True!"; else echo "False!"; fi<CR>
Do you see where the next step goes?
Utilities are needed for any floating point requirements.
Now try this utility, which I guess you already have: NUM=$( python -c "print(3.0/4.0)" ); echo "${NUM}"<CR> ; yes this works on Python 2.x.x and 3.x.x.
You now have your floating point number - BUT - how do you compare knowing there is an error report saying:
-bash: [: 0.75: integer expression expected ...
Now ksh is a different animal, similar to bash but has full floating point and integer maths capability and with a little work can create something like this little beauty:
DFT using pure ksh ONLY!

1 Like

Thanks for the inputs, In python is there a way to make it effective code or any other alternative approach

Here you go in bash, this REQUIRES integer number input for salary:
You will have to work out how to use floating point for input, it would be tedious but a draft so far...

#!/bin/bash

: > /tmp/salary.txt
echo 'EMPNAME | SALARY | Q1 | Q2 | Q3 | Q4 | Avg Q | Expected Sal | Incremented Sal | Performance |' > /tmp/salary.txt
while :
do
    printf "Enter employee name, QUIT or EXIT to finish:- "; read -r name
    if [ "${name}" = "QUIT" ] || [ "${name}" = "EXIT" ]
    then
        echo "Finalising file inside '/tmp/salary.txt'!"
        break
    fi
    printf "Enter employee salary:- "; read -r salary
    printf "Enter Q1:- "; read -r q1
    printf "Enter Q2:- "; read -r q2
    printf "Enter Q3:- "; read -r q3
    printf "Enter Q4:- "; read -r q4
    # Multiply all inputted INTEGER ONLY values by 100!
    salary=$(( salary*100 ))
    q1=$(( q1*100 ))
    q2=$(( q2*100 ))
    q3=$(( q3*100 ))
    q4=$(( q4*100 ))
    avg=$(( (q1+q2+q3+q4)/4 ))
    av=$(( (salary*avg) ))
    inc_salary=$(( (salary*av) ))
    exp_salary=$(( (salary+av) ))
    if [ "${avg}" -gt "700" ]
    then
        desc="BEST"
    fi
    if [ "${avg}" -le "700" ] && [ "${avg}" -ge "500" ]
    then
        desc="AVG"
    fi
    if [ "${avg}" -lt "500" ]
    then
        desc="ON TRACK"
    fi

    avg_str=$( printf "%.2f" "$(( avg ))e-2" )
    av_str=$( printf "%.2f" "$(( salary*avg ))e-6" )
    inc_salary_str=$( printf "%.2f" "$(( inc_salary ))e-12" )
    exp_salary_str=$( printf "%.2f" "$(( (salary*10000)+av ))e-6" )
    echo "$name | $(( salary/100 )) | $(( q1/100 )) | $(( q2/100 )) | $(( q3/100 )) | $(( q4/100 )) | ${avg_str} | ${exp_salary_str} | ${av_str} | ${desc} |"
    echo "$name | $(( salary/100 )) | $(( q1/100 )) | $(( q2/100 )) | $(( q3/100 )) | $(( q4/100 )) | ${avg_str} | ${exp_salary_str} | ${av_str} | ${desc} |" >> /tmp/salary.txt
done
clear
cat /tmp/salary.txt
exit 0

Results OSX 10.14.3, defaault bash terminal...

Enter employee name, QUIT or EXIT to finish:- Dave
Enter employee salary:- 11377
Enter Q1:- 3
Enter Q2:- 4
Enter Q3:- 5
Enter Q4:- 6
Dave | 11377 | 3 | 4 | 5 | 6 | 4.50 | 11888.96 | 511.96 | ON TRACK |
Enter employee name, QUIT or EXIT to finish:- Baz
Enter employee salary:- 12347
Enter Q1:- 6
Enter Q2:- 7
Enter Q3:- 6
Enter Q4:- 7
Baz | 12347 | 6 | 7 | 6 | 7 | 6.50 | 13149.55 | 802.55 | AVG |
Enter employee name, QUIT or EXIT to finish:- Tamsan
Enter employee salary:- 15678
Enter Q1:- 6
Enter Q2:- 7
Enter Q3:- 8
Enter Q4:- 8
Tamsan | 15678 | 6 | 7 | 8 | 8 | 7.25 | 16814.65 | 1136.66 | BEST |
Enter employee name, QUIT or EXIT to finish:- QUIT
Finalising file inside '/tmp/salary.txt'!

EMPNAME | SALARY | Q1 | Q2 | Q3 | Q4 | Avg Q | Expected Sal | Incremented Sal | Performance |
Dave | 11377 | 3 | 4 | 5 | 6 | 4.50 | 11888.96 | 511.96 | ON TRACK |
Baz | 12347 | 6 | 7 | 6 | 7 | 6.50 | 13149.55 | 802.55 | AVG |
Tamsan | 15678 | 6 | 7 | 8 | 8 | 7.25 | 16814.65 | 1136.66 | BEST |
bazza@amiga-MacBookPro:~/Desktop/Code/Shell$ 
bazza@amiga-MacBookPro:~/Desktop/Code/Shell$ # Now check with python...
bazza@amiga-MacBookPro:~/Desktop/Code/Shell$ 
bazza@amiga-MacBookPro:~/Desktop/Code/Shell$ python
Python 2.7.15+ (default, Nov 27 2018, 23:36:35) 
[GCC 7.3.0] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> ((11377*4.5)/100)+11377
11888.965
>>> ((12347*6.5)/100)+12347
13149.555
>>> ((15678*7.25)/100)+15678
16814.655
>>> _

Thanks a lot for your inputs, I would like to sort into descending order based one Avg Q while displaying the table

cat /tmp/salary.txt| sort -k 7

While using above code i am not able to sort based on Avg Q. Instead the header is also getting sorted

You wanted the python code in bash so don't run before you can walk!
The code, (#11), CAN be improved, it also has no error detection nor reporting, it has no means of going over a persons wrongly inputted data and it WILL overwrite the file on every (re)run.
I left those those anomalies out for you to to learn by working them out.

And line 3 of your python code does NOT do what you expect: av1 = float(sum / 4)
As your example always shows integer values for q1 to q4 the let's see what happens...

bazza@amiga-MacBookPro:~$ python
Python 2.7.15+ (default, Nov 27 2018, 23:36:35) 
[GCC 7.3.0] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> av1 = 5+6+7+7
>>> float(av1/4)
6.0
>>> exit()
 bazza@amiga-MacBookPro:~$ _

As you can see, the float is a conversion of integer division.
Either that is a bug or q1 to q4 MUST be, for example, sum = 5.0+6.0+7.0+7.0 to arrive at 6.25...

2 Likes

You need to tell sort the correct field delimiter. Try

sort -t"|" -k7g /tmp/salary.txt

(you see - no useless cat needed)

Unfortunately, sort doesn't offer special header treatment. You'll need to take it out of the sort process; like

{ read; echo $REPLY; sort -t"|" -k7bg; } </tmp/salary.txt

I think its not getting sorted properly

{ read; echo $REPLY; sort -t"|" -k7bg; } </tmp/salary.txt
EMPNAME | SALARY | Q1 | Q2 | Q3 | Q4 | Avg Q | Expected Sal | Incremented Sal | Performance |
Ron | 54980 | 3 | 2 | 4 | 1 | 2.50 | 56354.50 | 1374.50 | ON TRACK |
Lim | 87900 | 6 | 7 | 5 | 4 | 5.50 | 92734.50 | 4834.50 | AVG |
Bred | 67000 | 7 | 8 | 5 | 6 | 6.50 | 71355.00 | 4355.00 | AVG |
Expected would be sorted like below based on Avg Q
Bred
Lim
Ron

Instead can we get a proper tabular form instead of pipe which is getting confused. Ignore the spaces i took from Excel table but some how not able to make it proper tabular form

EMPNAME	SALARY	Q1	Q2	Q3	Q4	Avg	Expected Sal	Incremented Sal	Performance
Ron	54980	3	2	4	1	2.5	56354.5	1374.5	ON TRACK
Lim	87900	6	7	5	4	5.5	92734.5	4834.5	AVG
Bred	67000	7	8	5	6	6.5	71355	4355	AVG

I think it is sorted properly as sort has been told. If you want the result in descending order, use the -r (reverse) flag.

How about

{ read; echo $REPLY; sort -t"|" -k7bgr; } </tmp/salary.txt | tr "|" "\t" | column -ts"   "
EMPNAME    SALARY    Q1    Q2    Q3    Q4    Avg Q    Expected Sal    Incremented Sal    Performance 
Bred       67000     7     8     5     6     6.50     71355.00        4355.00            AVG 
Lim        87900     6     7     5     4     5.50     92734.50        4834.50            AVG 
Ron        54980     3     2     4     1     2.50     56354.50        1374.50            ON TRACK
2 Likes

As an addendum the 'bash' code works inside 'dash' too, without alteration except the shebang to point to 'dash' so therefore it is POSIX compliant...
In this case Linux Mint #!/bin/dash , and in my MBP OSX 10.14.3 Terminal, #!/usr/local/bin/dash ...

:slight_smile: Thank you for your answer. it helpful for me

Use Online Percentage Calculator.
w3percentagecalculator is free online accurate percentage calculator...