#! /usr/bin/awk -f

# For this script to work correctly, it must see the results of PC-2,
# DPC, PPC, TPPC, and TPPC-2 in that order for every input file
# processed.  Running csp-solve-all-consistency produces the correct
# input.
#
# It outputs a summary of the average REV3, REV, and CC counts; the
# average CPU time; and the ratio of problems detected to be non-PC
# compared to those detected to be non-PC by PC-2.

BEGIN {
    PC2 = "PC-2"
    DPC = "DPC"
    PPC = "PPC"
    TPPC = "TPPC"
    TPPC2 = "TPPC-2"
}

# Like assert macro is C, but we must provide a string explaining the
# failing condition.  This must be handled in END.
function assert(condition, string)
{
    if (! condition) {
	printf("%s:%d: assertion failed: %s\n", FILENAME, FNR,
	       string) > "/dev/stderr"
	_assert_exit = 1
	exit 1
    }
}

# This is called to incorporate the statistics of an instance of ALG
# into the overall statistics collected.
function getnew(alg)
{
    ++count[alg]
    
    # Check the label fields.  Make sure they are as expected.
    assert($2 == "REV3:" && $4 == "REV:" && $6 == "CC:" && $8 == "CPU:" &&
	   $10 == "PC-p:", "input file format must have changed")

    # Get the REV3, REV, and CC counts, as well as the CPU time for
    # the current record.
    rev3[alg] += $3
    rev[alg] += $5
    cc[alg] += $7
    cpu[alg] += $9
    
    if (pc_p == "no" && $11 == "no")
	++pc_p_no[alg]
}

function assert_not_pc_p_yes(alg)
{
    assert($11 != "yes", (alg " found problem PC but isn't that strong"))
}

# Print diagnostic if ALG failed to detect that a problem was non-PC.
# Don't call for DPC since it is expected to fail often.
function check_pc_p_no(alg)
{
    if (pc_p == "no" && $11 != "no")
	printf("%s: %s did not detect non-PC\n", inputfile, alg) > "/dev/stderr"
}

# Print the summary for ALG.
function output(alg)
{
    if (alg in count) {
	printf ("%6s[%d]: REV3: %9.2f  REV: %8.2f  CC: %11.2f"	\
		"  CPU: %5.2f  PC-p-no: %d/%d\n",
		alg, count[alg], (rev3[alg]/count[alg]),
		(rev[alg]/count[alg]), (cc[alg]/count[alg]),
		(cpu[alg]/count[alg]), pc_p_no[alg], pc_p_no_count)
    }
}


# Set `inputfile' to the name of the XML file used for the proceeding
# records.
/Input: / {
    inputfile = $2
}

/^PC-2:/ {
    pc_p = $11
    if (pc_p == "no")
	++pc_p_no_count
    assert(pc_p == "yes" || pc_p == "no", "PC-2 could not determine PC")
    getnew(PC2)
}
/^DPC:/ {
    assert_not_pc_p_yes(DPC)
    getnew(DPC)
    # Don't call check_pc_p_no for DPC.
}
/^PPC:/ {
    assert_not_pc_p_yes(PPC)
    getnew(PPC)
    check_pc_p_no(PPC)
    current_ppc_revs = $5;
}
/^TPPC:/ {
    assert_not_pc_p_yes(TPPC)
    getnew(TPPC)
    check_pc_p_no(TPPC)

    # It is expected that PPC and TPPC will perform the same number of
    # revisions when the problem is PPC.
    if ($11 == "?" && $5 != current_ppc_revs)
	printf("%s: PPC and TPPC differ in revisions: %d vs %d\n",
	       inputfile, current_ppc_revs, $5) > "/dev/stderr"
}
/^TPPC-2:/ {
    assert_not_pc_p_yes(TPPC2)
    getnew(TPPC2)
    check_pc_p_no(TPPC2)
}

END {
    if (_assert_exit)
	exit 1
    printf ("Input: ");
    for (i = 1; i < ARGC; i++)
	printf ARGV[i] " "
    printf ("\n")

    output(PC2)
    output(DPC)
    output(PPC)
    output(TPPC)
    output(TPPC2)
}
