# genquest.awk, 11 Apr 07
#

function new_page()
{
print ".bp"
if (new_subject == 1)
   {
   new_subject=0
   print ".tl ' '\\s-1%\\s+1'\\s-2accu: apr 07\\s+2'"
   }
else
   {
   print ".tl '" num_subject "_" num_ops "'\\s-1%\\s+1'\\s-2accu: apr 07\\s+2'"
#   print num_subject "_" num_ops
#   print ".sp 2l"
#   print ".tl '" num_subject "_" num_ops "'\\s-1%\\s+1'\\s-2accu: apr 07\\s+2'"
   }
}


function print_line(line_str)
{
print line_str
print ".br"
}

function rand_items(items)
{
for (v in items)
   {
   items[v]=rand() " " items[v]
   }
asort(items)
for (v in items)
   {
   sp_pos=index(items[v], " ")
   items[v]=substr(items[v], sp_pos+1)
   }
}

function gen_c1()
{
c[1]="4"
c[2]="5"
c[3]="6"
c[4]="8"
c[5]="9"
rand_items(c)
}

function gen_info()
{
id_count++
if (int(id_count % 21) == 0)
   id_count=1

cur_id[1]=id[id_count "1"]
cur_id[2]=id[id_count "2"]
cur_id[3]=id[id_count "3"]
cur_id[4]=non_id[id_count]
rand_items(cur_id)

gen_c1()

print ".sp 8l"
print_line(cur_id[1] " = " c[1] ";")
print_line(cur_id[2] " = " c[2] ";")
print_line(cur_id[3] " = " c[3] ";")
new_page()
}

function gen_mem_test()
{
print ".sp 12l"
print "\\h'1.2i'     remember  \\h'0.5i' would refer back\\h'0.5i' not seen"
print ".sp 1l"

rand_items(cur_id)
for (v in cur_id)
   {
   print "  " cur_id[v] " = \t____\t__\t__"
   print ".sp 1l"
   }
new_page()
}

function gen_ops(ops, TI, PL, EQ)
{
# Operators in precedence (higher to lower) order.

ops[1]="*"

if (PL == "PL")
   ops[2]="+"
else
   ops[2]="-"

ops[3]="<<"
ops[4]="<"

if (EQ == "EQ")
   ops[5]="=="
else
   ops[5]="!="

ops[6]="&"
ops[7]="^"
ops[8]="|"
ops[9]="&&"
ops[10]="||"
}


function rand_ops()
{
# Create an array of every dissimilar operator pair and
# randomise the ordering.
for (f_o in first_op)
   {
   for (s_o in second_op)
      {
      if (first_op[f_o] != second_op[s_o])
         op_pair[first_op[f_o] " " second_op[s_o]]=rand() " " first_op[f_o] "_" second_op[s_o]
      }
   }
asort(op_pair)
for (v in op_pair)
   {
   sp_pos=index(op_pair[v], " ")
   op_pair[v]=substr(op_pair[v], sp_pos+1)
   }
}


function get_op_oprand(op)
# Randomly extract one of the characters from the string op_op[op]
{
r_ch= substr(op_op[op], int(1+length(op_op[op])*rand()), 1)
#print op " " op_op[op] " " r_ch

if (rand() > 0.9)
   return toupper(operand[10*r_ch + int(1+6*rand())])
else
   return operand[10*r_ch + int(1+6*rand())]
}


function gen_oprand(left_op, middle_op, right_op)
{
middle_oprand=get_op_oprand(middle_op)

left_oprand=get_op_oprand(left_op)
while (left_oprand == middle_oprand)
   left_oprand=get_op_oprand(left_op)

#print left_op " " middle_op " " right_op
#print left_oprand " " middle_oprand

right_oprand=get_op_oprand(right_op)
while (right_oprand == middle_oprand)
   right_oprand=get_op_oprand(right_op)
}


function times_div_rem(op)
{
if (op == "*")
   {
   TI=rand()
   if (TI > 0.9)
      op="/"
   else if (TI > 0.75)
      op="%"
   }
return op
}

function print_expr(op_1, op_2)
{
print ".sp 2l"

op_1=times_div_rem(op_1)
op_2=times_div_rem(op_2)

if (rand() > 0.5)
   gen_oprand(op_1, op_1, op_2)
else
   gen_oprand(op_1, op_2, op_2)
printf("\\h'1i' %s  %s   %s   %s   %s\n", left_oprand, op_1, \
                                          middle_oprand,     \
                                          op_2, right_oprand)
}


function gen_subject(total_quest)
{
expr_per_quest=5
num_quest=0
expr_count=expr_per_quest+1

for (f_o in op_pair)
   {
   if (num_quest == total_quest)
      {
      return
      }
   if (int(expr_count % (expr_per_quest+1)) == 0)
      {
      expr_count=1
      gen_info()
      print ".sp 8l"
      print_line("				XXXXXXXXXXXXXXXXXX")
      print_line("				XXXXXXXXXXXXXXXXXX")
      print_line("				XXXXXXXXXXXXXXXXXX")
      print ".sp 4l"
      }
   expr_count++
   num_ops++
   split(op_pair[f_o], ops, "_")
   print_expr(ops[1], ops[2])
   if (int(expr_count % (expr_per_quest+1)) == 0)
      {
      gen_mem_test()
      num_quest++
      }
   }
}

BEGIN {
	new_subject=1
	num_subject=0
	id_count=0
	print ".pl +11.5i"
	print ".fz +2"
	print ".fam H"
	print ".ta 1.5i 2.9i 4.3i 5.0i"
	print ".ll 7.5i"
	id["1" "1"]="blue";  id["1" "2"]="red";  id["1" "3"]="green"
	id["2" "1"]="chair";  id["2" "2"]="table";  id["2" "3"]="sofa"
	id["3" "1"]="france";  id["3" "2"]="germany";  id["3" "3"]="sweden"
	id["4" "1"]="venus";  id["4" "2"]="mars";  id["4" "3"]="jupiter"
	id["5" "1"]="cow";  id["5" "2"]="sheep";  id["5" "3"]="pig"

	id["6" "1"]="fly";  id["6" "2"]="wasp";  id["6" "3"]="bee"
	id["7" "1"]="robin";  id["7" "2"]="blackbird";  id["7" "3"]="sparrow"
	id["8" "1"]="apple";  id["8" "2"]="pear";  id["8" "3"]="banana"
	id["9" "1"]="second";  id["9" "2"]="hour";  id["9" "3"]="minute"
	id["10" "1"]="oak";  id["10" "2"]="chestnut";  id["10" "3"]="elm"

	id["11" "1"]="january";  id["11" "2"]="june";  id["11" "3"]="october"
	id["12" "1"]="heart";  id["12" "2"]="lung";  id["12" "3"]="liver"
	id["13" "1"]="poker";  id["13" "2"]="scrabble";  id["13" "3"]="solitaire"
	id["14" "1"]="english";  id["14" "2"]="dutch";  id["14" "3"]="mandarin"
	id["15" "1"]="noun";  id["15" "2"]="adjective";  id["15" "3"]="verb"

	id["16" "1"]="shirt";  id["16" "2"]="trousers";  id["16" "3"]="dress"
	id["17" "1"]="spoon";  id["17" "2"]="knife";  id["17" "3"]="fork"
	id["18" "1"]="river";  id["18" "2"]="stream";  id["18" "3"]="canal"
	id["19" "1"]="plumber";  id["19" "2"]="painter";  id["19" "3"]="builder"
	id["20" "1"]="hammer";  id["20" "2"]="saw";  id["20" "3"]="screwdriver"
	non_id[1]="occult"
	non_id[2]="plastic"
	non_id[3]="pencil"
	non_id[4]="report"
	non_id[5]="hair"
	non_id[6]="string"
	non_id[7]="occult"
	non_id[8]="plastic"
	non_id[9]="pencil"
	non_id[10]="fence"
	non_id[11]="grass"
	non_id[12]="wood"
	non_id[13]="engine"
	non_id[14]="wheel"
	non_id[15]="tail"
	non_id[16]="chapter"
	non_id[17]="snake"
	non_id[18]="kettle"
	non_id[19]="atom"
	non_id[20]="propeller"
	non_id[21]="wax"
	non_id[22]="hot"
	non_id[23]="room"
	non_id[24]="exterior"
	non_id[25]="tangent"
	non_id[26]="comb"
	non_id[27]="lizard"
	non_id[28]="petrol"
	non_id[29]="saddle"
	non_id[30]="membrane"
# bit operands
	operand[11]="mask"
	operand[12]="flags"
	operand[13]="state"
	operand[14]="bits"
	operand[15]="options"
	operand[16]="0xff"
# boolean operands
	operand[21]="error"
	operand[22]="finished"
	operand[23]="flag"
	operand[24]="done"
	operand[25]="started"
	operand[26]="TRUE"
# anonymous operands
	operand[31]="resource"
	operand[32]="val"
	operand[33]="field"
	operand[34]="n"
	operand[35]="temp"
	operand[36]="7"
# numeric operands
	operand[41]="count"
	operand[42]="num"
	operand[43]="offset"
	operand[44]="rate"
	operand[45]="length"
	operand[46]="2"
# What kind of operand does this operator expect?
	op_op["|"]="12"
	op_op["&"]="12"
	op_op["^"]="12"
	op_op["||"]="22"
	op_op["&&"]="22"
	op_op["=="]="3" # could really be any expected type
	op_op["!="]="3"
	op_op["<"]="34"
	op_op["+"]="4"
	op_op["-"]="4"
	op_op["*"]="4"
	op_op["/"]="4"
	op_op["%"]="4"
	op_op["<<"]="124" # left operand is probably bit and right numeric
        print ".pl +11.5i"
	print ".fz +2"
	print ".fam H"
	print ".ta 1.5i 2.9i 4.3i 5.0i"
	print ".ll 7.5i"
	print ".tl ' '\\s-1%\\s+1'\\s-2accu: apr 07\\s+2'"
	}

$0 == "" {
	next
	}

# The six input fields are in two sets of three
# TI PL EQ TI PL EQ
# Upper case for the specified operator, lowercase for the alternative
	{
	num_subject++
        num_ops=0
	gen_ops(first_op, $1, $2, $3)
	gen_ops(second_op, $4, $5, $6)
	rand_ops()
	rand_items(non_id)
	gen_subject(18)
	asort(op_pair)
	rand_items(non_id)
        gen_subject(18)
	asort(op_pair)
        gen_subject(4)
	delete op_pair
	next
	}

END {
	}

