#! /usr/bin/gawk -f # Last edited on 2010-12-28 20:00:22 by stolfilocal BEGIN \ { # Reads from standard input a ".dat" file generated by {extract-votes.gawk}. # (first round, Presidential election only). # Outputs the {mu} coefficient and other information for each input record. # Parameters (define with "-v"): abort = -1; # Global counters: nrecords_read = 0; # Number of input records seen. nrecords_good = 0; # Number of records with positive weight. nrecords_written = 0; # Number of output records written. # Maximum number of real candidates (including BLANK and NULL): max_cands = 100; # Number of fields expected in ".dat" file (set from first record): num_fields = -1; # Low and high Serra {pcp} for zero Marina vote-stealing: loS = 0.050; hiS = 0.850; # Noise fudge factor (fraction): tad = 0.050; # Baseline {pcp} for Marina: baseM = 0.050; } ( abort >= 0) { exit abort; } /^[A-Z][A-Z][ ]+[0-9]/ \ { nrecords_read ++; # We should have at least 2 cands besides BLANK and NULL: if ((NF < 9 + 4) || (NF > 9 + max_cands)) { data_error(("wrong number of fields " NF)); } # Check constancy of the number of fields: if ((FNR > 1) && (NF != num_fields)) { data_error(("wrong number of fields " NF " expected " num_fields)); } num_fields = NF; # Grab fields: zon=$2; sec=$3; lov=$4; loc=$5; car=$6; ele=$7; aus=$8; pre=$9; bra=$10; nul=$11; dil=$12; ser=$13; mar=$14; pli=$15; # Consistency of office code: if (car != 1) { data_error(("wrong office = \"" car "\"")); } # Check consistency of vote totals: if (! is_num(ele,0,999999999)) { data_error(("invalid {ele} = \"" ele "\"")); } if (! is_num(aus,0,ele)) { data_error(("invalid {aus} = \"" aus "\"")); } if (! is_num(pre,0,ele)) { data_error(("invalid {pre} = \"" pre "\"")); } if (pre + aus != ele) { data_error(("wrong vote counts ele = " ele " aus = " aus " pre = " pre)); } # Compute {pcp} percentages: pcpD = dil/pre; pcpS = ser/pre; pcpM = mar/pre; pcpP = pli/pre; pcpBRA = bra/pre; pcpNUL = nul/pre; # Compute the Marina stealing coefficient {muc} and its weight {muw}: if ((pcpS <= loS) || (pcpS >= hiS)) { muc = 0.000; muw = 0.000; } else { fem = para(pcpS,loS-tad,hiS+tad) muc = (pcpM - baseM)/sqrt(fem*fem + tad*tad); muw = para(pcpS,loS,hiS); nrecords_good ++; } # Write outut file: printf "%s.%s.%s.%s %4d %4d", zon, loc, sec, lov, ele, pre; printf " %6.4f %8.6f", muw, muc; printf " %6.4f %6.4f %6.4f %6.4f", pcpD, pcpS, pcpM, pcpP; printf " %6.4f %6.4f", pcpBRA, pcpNUL; printf "\n"; nrecords_written ++; next; } // { data_error(("invalid record format")); } function para(p,lo,hi) { # The vote-stealing basis function: return 4*(p - lo)*(hi - p)/(hi - lo); } END \ { if ( abort >= 0) { exit abort; } printf "%8d records read\n", nrecords_read > "/dev/stderr"; printf "%8d records written\n", nrecords_written > "/dev/stderr"; printf "%8d records with positive weight\n", nrecords_good > "/dev/stderr"; printf "%8d records with zero weight\n", nrecords_written - nrecords_good > "/dev/stderr"; } function is_num(x,lo,hi) { if (x !~ /^[0-9]+$/) { return 0; }; if (x+0 < lo) { return 0; } if (x+0 > hi) { return 0; } return 1; } function is_frac(x,lo,hi) { if (x !~ /^[0-9]+([.][0-9]+|)$/) { return 0; }; if (x+0 < lo) { return 0; } if (x+0 > hi) { return 0; } return 1; } function data_error(msg) { printf "%s:%d: ** %s\n", FILENAME, FNR, msg > "/dev/stderr"; printf " %s\n", $0 > "/dev/stderr"; abort = 1; exit(abort); } function data_warning(msg) { printf "%s:%d: !! %s\n", FILENAME, FNR, msg > "/dev/stderr"; printf " %s\n", $0 > "/dev/stderr"; } function arg_error(msg) { printf "** %s\n", msg > "/dev/stderr"; abort = 1; exit(abort); } function prog_error(msg) { printf "** PROGRAM ERROR - %s\n", msg > "/dev/stderr"; abort = 1; exit(abort); }