#
# getprec.awk,  1 Jan 08
#
# 13 Nov 07 DJ Added name kind processing
# 29 Oct 07 DJ Added prec_order parameter and support
#  5 Jul 06 DJ Initial release

function correct_answer(prec_order)
{
total_correct_op+=2
total_correct_prec_order[prec_order]++
op_count[first_op]++
op_count[second_op]++
op_correct[first_op]++
op_correct[second_op]++
correct_paren++
pair_correct[op_pair_str]++
paren_usage_correct=1
}

function wrong_answer(prec_order)
{
total_wrong_op+=2
total_wrong_prec_order[prec_order]++
op_count[first_op]++
op_count[second_op]++
op_wrong[first_op]++
op_wrong[second_op]++
pair_wrong[op_pair_str]++
paren_usage_correct=0
}

function op_matches_name(match_op, op_name, is_first_op)
{
if (op_kind[match_op] == ANON)
   return 0
if (op_kind[match_op] == name_kind[op_name])
   return 1
if (op_kind[match_op] == "<<")
   {
   if (is_first_op)
      return name_kind[op_name] == ARITH
   else
      return (name_kind[op_name] == BITWISE)
   }
return 0
}

function op_opposite_name(other_op, op_name, is_first_op)
{
if ((op_kind[other_op] == ARITH) &&
    (name_kind[op_name] == BITWISE))
   return 1
if ((op_kind[other_op] == BITWISE) &&
    (name_kind[op_name] == ARITH))
   return 1

if (op_kind[other_op] == "<<")
   {
   if (is_first_op)
      return name_kind[op_name] == ARITH
   else
      return (name_kind[op_name] == BITWISE)
   }
return 0
}

function op_matches_op(op_1, op_2)
{
if (op_kind[op_1] == "<<")
   return 0
if (op_kind[op_1] == op_kind[op_2])
   return 1

return 0
}

function count_pat(pat_str)
{
if (paren_usage_correct)
   op_pat[pat_str " CO"]++
else
   op_pat[pat_str " WR"]++
}

function count_expr_kind(op_1, op_2, mid_operand)
{
if (op_prec[op_1] == op_prec[op_2])
   return
if (op_prec[op_1] > op_prec[op_2])
   {
   is_first_op=1
   cor_op=op_1
   other_op=op_2
   }
else
   {
   is_first_op=0
   cor_op=op_2
   other_op=op_1
   }
if (op_matches_name(cor_op, mid_operand, is_first_op))
   {
   ek_total_name_with_op++
   if (paren_usage_correct)
      ek_total_cor_name_with_op++
   else
      ek_total_wrng_name_with_op++
   if (op_matches_name(other_op, mid_operand, is_first_op==0))
#   if (op_opposite_name(other_op, mid_operand, is_first_op))
      {
      count_pat(" MN  OM")
#      print "MN OM " $0
      }
   else
      count_pat(" MN NOM")
   }
else
   {
   ek_total_no_name_with_op++
   if (paren_usage_correct)
      ek_total_cor_no_name_with_op++
   else
      ek_total_wrng_no_name_with_op++
   if (op_matches_name(other_op, mid_operand, is_first_op==0))
#   if (op_opposite_name(other_op, mid_operand, is_first_op))
      count_pat("NMN  OM")
   else
      {
      count_pat("NMN NOM")
#      print "NMN NOM " $0
      }
   }
if (op_matches_name(other_op, mid_operand, is_first_op==0))
   {
   ek_total_name_with_other++
   if (paren_usage_correct)
      ek_total_cor_name_with_other++
   else
      ek_total_wrng_name_with_other++
   }
else
   {
   ek_total_no_name_with_other++
   if (paren_usage_correct)
      ek_total_cor_no_name_with_other++
   else
      ek_total_wrng_no_name_with_other++
   }
}

function count_answer_kind(parened_op, other_op, mid_operand, is_first_op)
{
if (op_matches_name(parened_op, mid_operand, is_first_op))
   {
   total_name_with_op++
   if (paren_usage_correct)
      total_cor_name_with_op++
   else
      total_wrng_name_with_op++
#   if (op_matches_name(other_op, mid_operand, is_first_op==0))
#   if (op_opposite_name(other_op, mid_operand, is_first_op))
#      count_pat(" MN  OM")
#   else
#      count_pat(" MN NOM")
   }
else
   {
   total_no_name_with_op++
   if (paren_usage_correct)
      total_cor_no_name_with_op++
   else
      total_wrng_no_name_with_op++
#   if (op_matches_name(other_op, mid_operand, is_first_op==0))
#   if (op_opposite_name(other_op, mid_operand, is_first_op))
#      count_pat("NMN  OM")
#   else
#      count_pat("NMN NOM")
   }

if (op_matches_name(other_op, mid_operand, is_first_op==0))
   {
   total_name_with_other++
   if (paren_usage_correct)
      total_cor_name_with_other++
   else
      total_wrng_name_with_other++
   }
else
   {
   total_no_name_with_other++
   if (paren_usage_correct)
      total_cor_no_name_with_other++
   else
      total_wrng_no_name_with_other++
   }

#if (op_kind[op_2] == ANON)
#   {
#   t=op_1
#   op_1=op_2
#   op_2=t
#   }
#if (op_kind[op_2] == ARITH)
#   {
#   t=op_1
#   op_1=op_2
#   op_2=t
#   }
#if (paren_usage_correct)
#   expr_cor[op_kind[op_1] " " name_kind[mid_operand] " " op_kind[op_2]]++
#else
#   expr_wrng[op_kind[op_1] " " name_kind[mid_operand] " " op_kind[op_2]]++
}

BEGIN {
	line_num=0
	in_answers=0
	num_answers=0
	correct_paren=0
	incorrect_paren=0
	first_high=1
	equal_prec=2
	second_high=3
	op_prec["*"]=13 ; op_prec["/"]=13 ; op_prec["%"]=13
	op_prec["+"]=12 ; op_prec["-"]=12
	op_prec["<<"]=11 ;
# op_prec[">>"]=11
	op_prec["<"]=10 ;
# op_prec[">"]=10 ; op_prec["<="]=10 ; op_prec[">="]=10
	op_prec["=="]=9 ; op_prec["!="]=9
	op_prec["&"]=8
	op_prec["^"]=7
	op_prec["|"]=6
	op_prec["&&"]=5
	op_prec["||"]=4
	op_str["*"]="times" ; op_str["/"]="div" ; op_str["%"]="rem"
	op_str["+"]="plus" ; op_str["-"]="minus"
	op_str["<<"]="lshift" ; op_str[">>"]="rshift"
	op_str["<"]="lt" ; op_str[">"]="gt" ; op_str["<="]="le" ; op_str[">="]="ge"
	op_str["=="]="eq" ; op_str["!="]="ne"
	op_str["&"]="band"
	op_str["^"]="xor"
	op_str["|"]="bor"
	op_str["&&"]="land"
	op_str["||"]="lor"
	op_map_op["*"]="*" ; op_map_op["/"]="/" ; op_map_op["%"]="%"
	op_map_op["+"]="+" ; op_map_op["-"]="-"
	op_map_op["<<"]="<<" ; op_map_op[">>"]="<<"
	op_map_op["<"]="<" ; op_map_op[">"]="<" ; op_map_op["<="]="<" ; op_map_op[">="]="<"
	op_map_op["=="]="==" ; op_map_op["!="]="!="
	op_map_op["&"]="&"
	op_map_op["^"]="^"
	op_map_op["|"]="|"
	op_map_op["&&"]="&&"
	op_map_op["||"]="||"
#	all_ops_count=split("* / % + - << >> < > <= >= == != & ^ | && ||", op_list)
	all_ops_count=split("* / % + - << < == != & ^ | && ||", op_list)

	ARITH="arithmetic"
	BITWISE="bitwise"
	LOGICAL="logical"
	ANON="anon"
	SHIFT="<<"
	name_kind["error"]=BITWISE
	name_kind["flags"]=BITWISE
	name_kind["state"]=BITWISE
	name_kind["bits"]=BITWISE
	name_kind["options"]=BITWISE
	name_kind["0xff"]=BITWISE
       	name_kind["mask"]=BITWISE
       	name_kind["finished"]=BITWISE
       	name_kind["flag"]=BITWISE
       	name_kind["done"]=BITWISE
      	name_kind["started"]=BITWISE
       	name_kind["true"]=LOGICAL
       	name_kind["count"]=ARITH
       	name_kind["num"]=ARITH
       	name_kind["offset"]=ARITH
       	name_kind["rate"]=ARITH
       	name_kind["length"]=ARITH
       	name_kind["2"]=ANON
       	name_kind["resource"]=ANON
       	name_kind["val"]=ANON
       	name_kind["field"]=ANON
       	name_kind["n"]=ARITH
       	name_kind["temp"]=ANON
       	name_kind["7"]=ANON
	op_kind["*"]=ARITH ; op_kind["/"]=ARITH ; op_kind["%"]=ARITH
	op_kind["+"]=ARITH ; op_kind["-"]=ARITH
	op_kind["<"]=ARITH ; op_kind[">"]=ARITH
        op_kind["<="]=ARITH ; op_kind[">="]=ARITH
	op_kind["=="]=ANON ; op_kind["!="]=ANON
	op_kind["&"]=BITWISE ; op_kind["^"]=BITWISE ; op_kind["|"]=BITWISE
	op_kind["&&"]=LOGICAL ; op_kind["||"]=LOGICAL
	op_kind["<<"]=SHIFT ; op_kind[">>"]=SHIFT
	}

	{
	line_num++
	}

($2 == ":") && ($4 == ":") {
	start_num_answers=num_answers
	cur_total_correct_op=total_correct_op
	years_exp=$5;
	next
	}

$1 == "\\h'1i'" {
	if (in_answers == 0)
	   next
	e_parened=0
	first_op=$3
	second_op=$6
	if ($4 == "(")
	   e_parened=2
	else if ($5 == ")")
	   e_parened=1
	if (e_parened == 0)
	   {
	   if (($NF == "no_answer") || ($NF == "skipped") || ($NF == "up_to_compiler") || ($NF == "ambiguous_answer"))
	      next
	   print ">> " line_num " " $0
	   }
	if ((op_prec[first_op] == "") || (op_prec[second_op] == ""))
	   print ">> unknown operator " first_op " " second_op
	op_pair_str=first_op " " second_op
	total_pairs[op_pair_str]++
	if (op_prec[first_op] > op_prec[second_op])
	   {
	   if (e_parened == 1)
	      correct_answer(first_high)
	   else
	      wrong_answer(first_high)
	   }
	if (op_prec[first_op] == op_prec[second_op])
	   {
	   if (e_parened == 1)
	      correct_answer(equal_prec)
	   else
	      wrong_answer(equal_prec)
	   }
	if (op_prec[first_op] < op_prec[second_op])
	   {
	   if (e_parened == 2)
	      correct_answer(second_high)
	   else
	      wrong_answer(second_high)
	   }
	if (op_matches_op(first_op, second_op))
	   {
	   total_same_op_kind++
	   op_kind_total[op_kind[first_op]]++
	   if (paren_usage_correct)
	      {
	      total_cor_same_op_kind++
	      op_kind_cor_total[op_kind[first_op]]++
	      }
	   else
	      total_wrng_same_op_kind++
	   }
	else
	   {
	   if (e_parened == 1)
	      {
	      count_expr_kind(first_op, second_op, tolower($4))
	      count_answer_kind(first_op, second_op, tolower($4), 1)
	      }
	   else
	      {
	      count_expr_kind(first_op, second_op, tolower($5))
	      count_answer_kind(second_op, first_op, tolower($5), 0)
	      }
	   }
	num_answers++
	next
	}

$0 == "Strategies" {
	in_answers=1
	next
	}

$0 == "FINISH" {
	in_answers=0
	printf("%d  %d  %5.2f\n", (num_answers-start_num_answers),  years_exp,\
 (100.0*(total_correct_op-cur_total_correct_op)/2)/(0.0001+num_answers-start_num_answers))
	total_years_exp+=years_exp
	next
	}

	{
	next
	}

END {
	TEMP_FILE="dy" systime()

	print "total years experience " total_years_exp
	print "Total answers " num_answers " correct " correct_paren
	print "Correct " total_correct_prec_order[first_high] " " \
			total_correct_prec_order[equal_prec] " " \
			total_correct_prec_order[second_high]
	print "Wrong " total_wrong_prec_order[first_high] " " \
			total_wrong_prec_order[equal_prec] " " \
			total_wrong_prec_order[second_high]
	printf("same op kind %d    correct %4.1f wrong %4.1f\n",
		 total_same_op_kind, \
		 (100.0*total_cor_same_op_kind)/total_same_op_kind, \
		 (100.0*total_wrng_same_op_kind)/total_same_op_kind)
#	printf("ANON  %d  %4.1f ARITH  %d  %4.1f  BITWISE  %d  %4.1f  LOGICAL  %d  %4.1f  SHIFT  %d  %4.1f\n",
	printf("ANON  %d  %4.1f ARITH  %d  %4.1f  BITWISE  %d  %4.1f  LOGICAL  %d  %4.1f\n",
		 op_kind_total[ANON], \
		 (100.0*op_kind_cor_total[ANON])/op_kind_total[ANON], \
		 op_kind_total[ARITH], \
		 (100.0*op_kind_cor_total[ARITH])/op_kind_total[ARITH], \
		 op_kind_total[BITWISE], \
		 (100.0*op_kind_cor_total[BITWISE])/op_kind_total[BITWISE], \
		 op_kind_total[LOGICAL], \
		 (100.0*op_kind_cor_total[LOGICAL])/op_kind_total[LOGICAL])
#		 op_kind_total[SHIFT], \
#		 (100.0*op_kind_cor_total[SHIFT])/op_kind_total[SHIFT])

	printf("ek name with op %d    correct %4.1f wrong %4.1f\n",
		 ek_total_name_with_op, \
		 (100.0*ek_total_cor_name_with_op)/ek_total_name_with_op, \
		 (100.0*ek_total_wrng_name_with_op)/ek_total_name_with_op)
	printf("ek no name with op %d correct %4.1f wrong %4.1f\n",
		 ek_total_no_name_with_op, \
		 (100.0*ek_total_cor_no_name_with_op)/ek_total_no_name_with_op, \
		 (100.0*ek_total_wrng_no_name_with_op)/ek_total_no_name_with_op)
	printf("ek name with other %d    correct %4.1f wrong %4.1f\n",
		 ek_total_name_with_other, \
		 (100.0*ek_total_cor_name_with_other)/ek_total_name_with_other, \
		 (100.0*ek_total_wrng_name_with_other)/ek_total_name_with_other)
	printf("ek no name with other %d correct %4.1f wrong %4.1f\n",
		 ek_total_no_name_with_other, \
		 (100.0*ek_total_cor_no_name_with_other)/ek_total_no_name_with_other, \
		 (100.0*ek_total_wrng_no_name_with_other)/ek_total_no_name_with_other)
	printf("name with op %d    correct %4.1f wrong %4.1f\n",
		 total_name_with_op, \
		 (100.0*total_cor_name_with_op)/total_name_with_op, \
		 (100.0*total_wrng_name_with_op)/total_name_with_op)
	printf("no name with op %d correct %4.1f wrong %4.1f\n",
		 total_no_name_with_op, \
		 (100.0*total_cor_no_name_with_op)/total_no_name_with_op, \
		 (100.0*total_wrng_no_name_with_op)/total_no_name_with_op)
	printf("name with other %d    correct %4.1f wrong %4.1f\n",
		 total_name_with_other, \
		 (100.0*total_cor_name_with_other)/total_name_with_other, \
		 (100.0*total_wrng_name_with_other)/total_name_with_other)
	printf("no name with other %d correct %4.1f wrong %4.1f\n",
		 total_no_name_with_other, \
		 (100.0*total_cor_no_name_with_other)/total_no_name_with_other, \
		 (100.0*total_wrng_no_name_with_other)/total_no_name_with_other)
	print "Op patterns"
	printf("") > TEMP_FILE
	for (i in op_pat)
	   print i " " op_pat[i] >> TEMP_FILE
	close(TEMP_FILE)
	system("sort < " TEMP_FILE)
	print "Correct paren"
	for (i in expr_cor)
	   print i " " expr_cor[i]
	print "Incorrect paren"
	for (i in expr_cor)
	   print i " " expr_wrng[i]
	for (op in total_pairs)
	   printf("%6s  %4d  %5.1f\n", op, total_pairs[op], (100.0*pair_correct[op])/total_pairs[op])

	for (op_1 in op_str)
	   for (op_2 in op_str)
	      {
	      pair_total= pair_correct[op_1 " " op_2] + pair_correct[op_2 " " op_1]
	      if (pair_total > 0)
		 if (op_prec[op_1] > op_prec[op_2])
		    print op_str[op_1] " " op_str[op_2] " " pair_total
		 else
		    if (op_prec[op_1] != op_prec[op_2])
		       print op_str[op_2] " " op_str[op_1] " " pair_total
	      }
	print ""

	print "op pairs wrong: alphabetical"
	printf("") > TEMP_FILE
	for (op_1 in op_str)
	   for (op_2 in op_str)
	      {
	      pair_total= pair_wrong[op_1 " " op_2] + pair_wrong[op_2 " " op_1]
	      if (pair_total > 0)
		 print op_str[op_1] " " op_str[op_2] " " pair_total >> TEMP_FILE
	      }
	close(TEMP_FILE)
	system("sort < " TEMP_FILE)

	print "op pairs wrong: precedence order"
	printf("") > TEMP_FILE
	for (op_1 in op_str)
	   for (op_2 in op_str)
	      {
	      pair_total= pair_wrong[op_1 " " op_2] + pair_wrong[op_2 " " op_1]
	      if (pair_total > 0)
		 if (op_prec[op_1] < op_prec[op_2])
		    print op_str[op_1] " " op_str[op_2] " " pair_total >> TEMP_FILE
		 else
		    if (op_prec[op_1] != op_prec[op_2])
		       print op_str[op_2] " " op_str[op_1] " " pair_total >> TEMP_FILE
	      }
	close(TEMP_FILE)
	system("sort < " TEMP_FILE)

	print "correct op pairs"
	printf("     ")
	for (op_1=1; op_1 <= all_ops_count; op_1++)
	   printf(", %6s", op_list[op_1])
	printf("\n")
	for (op_1=1; op_1 <= all_ops_count; op_1++)
	   {
	   printf("%2s", op_list[op_1])
	   for (op_2=1; op_2 <= op_1; op_2++)
	      {
	      pair_total= pair_correct[op_list[op_1] " " op_list[op_2]] + pair_correct[op_list[op_2] " " op_list[op_1]] + \
	                  pair_wrong[op_list[op_1] " " op_list[op_2]] + pair_wrong[op_list[op_2] " " op_list[op_1]]
	      correct_total= pair_correct[op_list[op_1] " " op_list[op_2]] + pair_correct[op_list[op_2] " " op_list[op_1]]
	      if (pair_total)
	         printf(", %3d(%2d)", int((100.0*correct_total)/pair_total), pair_total)
	      else
	         printf(", %7s", "-")
	      }
	   printf("\n")
	   }

	printf("") > TEMP_FILE
	print "ops in correct answers"
	for (op in op_correct)
	   printf("%s %5.2f %5d\n", op, 100.0*op_correct[op]/op_count[op], op_count[op]) >> TEMP_FILE
	close(TEMP_FILE)
	system("sort -gr -k2 < " TEMP_FILE)

	printf("") > TEMP_FILE
	print "ops in wrong answers"
	for (op in op_wrong)
	   printf("%s %5.2f %5d\n", op, 100.0*op_wrong[op]/op_count[op], op_count[op]) >> TEMP_FILE
	close(TEMP_FILE)
	system("sort -gr -k2 < " TEMP_FILE)

	system("rm " TEMP_FILE)
	}

