# to unpack, use  unshar <this file>
echo x - README 1>&2
sed 's/^X//' >README <<'@@@End of README'
XPCWC Moderator's Kit
X
X* Preface
X
XThese instructions were not originally part of the kit, but were
Xadded by Mark Brader.  There's nothing hard here, but the kit did
Xtake the point of view that it was obvious how to use it, and that
Xprobably isn't the case for everyone.  If something seems unclear or
Xunnecessarily complicated, feel free to improve it before forwarding
Xthe kit to the next moderator.
X
X[I have done so, or at least tried -- Ilana Stern, June 1994]
X[Further improvements by Mark Brader, April 1997.]
X[Additional notes added by Phil Rose, July 1997.]
X[Editing of UNIX hints by William Johnston, February 1998.]
X
XIt is assumed that you're using some form of UNIX.  If you're not,
Xthere are a few people in the newsgroup who will run the scoring
Xstuff for you, if you ask.
X
XIf this file is named README, then the rest of the files that you
Xneed have also been unpacked out of the same shell archive.  (If you
Xare not on a UNIX system, you may have requested that the files be
Xsent in some other way.) Note that if you obtained this kit from
Xa DOS system (e.g. the archive) it may have 'carriage returns' at the
Xend of each line.  These must be removed from the script files to
Xenable them to run.
X
X* Posting the contest announcement
X
XYou should make a copy of the file "announcement" and edit it to
Xsupply the contest number, the dates, and the word to be clued; and
Xof course your name and email address, along with any special
Xinstructions for emailing you.  Some of the jokes in it will get
Xstale; feel free to update it.  Scan the file for '?' and "#".  When
Xyou are done, there shouldn't be any left.  Post this file to
Xrec.puzzles.crosswords, and save a copy of the posting for
Xreference.
X
XAlso, you should email a copy to the CCC mailing list owner, so it
Xwill be distributed as soon as possible via the list.  As of July
X1997 the list owner is James Lundon <jlundon@dsc.ie> --
Xplease update this item in the moderator kit as necessary.
X
X* Preparing and Posting the Ballot
X
XAs the clues come in, save them somewhere, either in separate files
Xor a single mailbox, whatever is more convenient for you.  When the
Xtime for clues to arrive is up, you may wish to shuffle them into a
Xrandom sequence, if it's convenient for you to do this.  You may wish
Xto use the "shuffle" script included in this kit. If the clues are in
Xa single file, separated by -------- dividers, then the UNIX command
X"shuffle <filename>" will rearrange them at random.
X
XWhen the time for entries is finished, create the following clue
Xfiles.  (The filenames don't matter, but we'll use specific names to
Xmake it easy to refer to them.)
X
X1) "entries":
X
X   All the clues, explanations, and authors, with numbers from 1
X   to whatever.  This is mostly to help you create the other files.
X   One way to make this is to just make a copy of the big clue file (you
X   will probably want to leave the original alone, so you can refer to
X   it just in case, and also so you can check who can moderate the next
X   contest).  Edit it by removing message headers and extraneous stuff.  
X
X   Make sure each clue has an "Entrant:" line giving the submitter's
X   name.  If the clue submitter does not follow the new
X   recommended format, you may have to construct this from the mail
X   message's "From:" header line, or the signature.  Make sure the
X   colon ":" is present after the word "Entrant"; the scoring program
X   needs it! Write the clues in the following format, inserting the
X   clue number on each line where # is shown here. Note: the e-mail
X   address is optional and its exact syntax is unimportant.
X
X	# Entrant: J. Doe <doe@hostname.edu>
X	#) This is J. Doe's clue, which happens
X	#) to take up two lines.  
X
X		This is J. Doe's explanation
X		of how his clue works.  Notice
X		no numbers are necessary here,
X		and this is indented by one tab.
X
X   Put "--------" lines in between the clues as separators.
X
X   The clue numbers MUST be consecutive from 1 onward.  With the
X   numerical scoring method you can accept bonus clues; in that case
X   these MUST be given NEGATIVE numbers from -1 on.
X
X2) "clues"
X
X   Copy just the clues out of "entries".  An easy way to do this with
X   a UNIX system is to use the command
X
X	grep "^-*[0-9]*)" entries > clues
X
X   but if you don't have this capability, you can edit the file by hand.
X   You may want to edit the result anyway to make multiline clues look 
X   nicer by removing extra clue numbers in front of any second and later
X   lines, and maybe separate the clues by blank lines.  You might end
X   up with:
X
X	1) Clue one (10)
X	2) Clue the second, which is the one after the clue that
X	   was number one (10)
X	3) Clue three (10)
X	-1) The first bonus clue (10)
X	-2) The second bonus clue (10)
X
X3) "cluesexplained"
X
X   Copy "entries" and remove the author lines.  An easy way to do this
X   with a UNIX system is to use the command
X
X	grep -v "Entrant: " entries > cluesexplained
X
X   This gives a file with clues and explanations, but no author names.
X 
X4) "summary"
X
X   If you will be using the numerical scoring method, make yet another
X   copy of "entries" and delete the explanations, leaving you with just 
X   numbered authors and clues.  This will be used in scoring.  If the
X   "entries" file is in the proper format, the UNIX command
X
X	grep "^-*[0-9]" entries > summary
X
X   will produce the correct format, but do check to see that nothing
X   was lost.
X
XNow, choose a voting method, either the clue-ranking or the numerical.
X(Most recent contests have used the numerical method.)  Make a copy of 
Xthe file "how-to-vote.<method>", and edit it the way you did with
Xthe copy of "announcement", filling in the appropriate places, to
Xcreate the ballot posting.  The two files "clues" and "cluesexplained"
Xthat you just created will, of course, provide the content for two of
Xthe places that you have to fill in.  Especially if the ballot is
Xlarge, some moderators prefer to put these two files in one posting
Xand the voting instructions in a separate one.  Do as you will.
X
XPost the ballot posting or postings to rec.puzzles.crosswords,
Xpreferably with a References line giving the Message-Id from the
Xannouncement posting.  Again, save a copy of the posting, and email
Xa copy to the CCC list owner for quicker distribution.
X
X* Preparing and Posting the Results
X
XNow the votes will start arriving.  Create a directory under the
Xdirectory where you've put the other PCWC materials (we'll call it
X"votes" here), and save each vote message into a SEPARATE FILE
Xthere.  Make sure that each file is in the correct format as
Xdescribed in the ballot posting. Watch out for long lines that wrap;
Xthey will need attention to their numbering.
X
XWhen the time for votes to arrive is up, run the scoring program.
XIf you have chosen clue-ranking, run "score" and also "comments".
XIf you have chosen numerical scoring, run "score.numerical" which
Xalso tabulates the comments.
X
XTo do this, you mark the program files as executable by doing 
X"chmod +x" followed by the filenames, and then run them:
X
XFor the numerical method, just do:
X
X	score.numerical summary votes/* > score-out
X
Xwhere instead of 'summary' you put the name of the fourth file created
Xfrom the original entry file (the one with just names of authors and
Xtheir clues, all numbered).  The score-out file will contain
Xa fairly complete posting with ranked scores and comments, with 
Xauthors' names for the top clues.
X
XIf you're using the ranking method, run:
X
X	score.ranking NCLUES votes/* > score-out
X	comments votes/*
X
Xwhere instead of NCLUES you write the number of clues you received.
XThe file "score-out" will contain the scoring table, from which you
Xwill identify the winner; and a series of files "comment1",
X"comment2", etc.  will contain the voters' comments on the different
Xclues.  Now you edit all these files together yourself, together with
Xthe list of clues from the ballot posting and the names of the better
Xclue-writers (don't embarrass the authors of the bad ones) from the
Xoriginal mail with the clues, and create the result posting.
X
XNow, in either case, insert any overall commentary of your own that
Xyou like at the top, and post the results to rec.puzzles.crosswords,
Xpreferably with a References line giving the Message-Id's from the
Xannouncement and ballot postings.  Once again, be sure to email a
Xcopy to the CCC list owner.
X
X* In Case of Difficulty, Break Glass
X
XBecause of variations between different systems, the scoring step may
Xnot go as easily as implied above.  In particular, if you have a
Xversion of UNIX that does not understand #! lines, then none of the
Xprograms will work correctly.  In that case, edit "score.ranking"
Xor "score.numerical" to put a line consisting only of a colon at the
Xfront of it, and put the word "sh" on the front of the command line
Xwhere you invoke the program.
X
XThe "comments" program in the ranking method will also fail if #! is
Xnot recognized; in that case, delete that line from the top and put
Xthe word "perl" before "comments" when you invoke it.  If your system
Xrecogizes #! but perl is not where "comments" expects it to be, you
Xwill have to edit the #! line.  (Use "type perl" or "which perl" to
Xfind out where perl is.)  Finally, your system might not have perl at
Xall, in which case you would have to edit the comments in by hand or
Xdisappoint your readers by suppressing them.  (Anyone want to rewrite
X"comments" for greater portability, either using older perl
Xconstructs, or sh and (old) awk?)
X
XAlso, if voters don't adhere strictly to the ballot format, you may
Xget errors from the tabulation scripts -- or the votes may not even
Xbe counted.  Make sure that the dashed lines are present, and that
Xthe votes are in the format required by your chosen scoring method.
X
@@@End of README
echo x - announcement 1>&2
sed 's/^X//' >announcement <<'@@@End of announcement'
XSubject: PCWC ?? announcement
XExpires: 3 weeks
XReply-To: ???????
X
XPEOPLE'S CLUE WRITING COMPETITION NUMBER ??
X
XWelcome to PCWC ??, a clue-writing contest created by Guy Jacobson.
XInstead of just one judge, this contest is judged by everyone who
Xwants to vote.
X
XThe word:                 ????????
XThe moderator:            ????????
XThe schedule:
X  ?? ???ember 23:59 ??T   Deadline for entries
X  ?? ???ember             I'll post the ballot
X  ?? ???ember 23:59 ??T   Deadline for votes
X  ?? ???ember             I'll post the results
X
XTo enter, write a cryptic-crossword clue for the word above, and
Xe-mail it to the moderator before the deadline.  Please use the form
Xfor entries described below.  One entry per person.  Do not post any
Xclues to the newsgroup.
X
XThe moderator will post a ballot that lists all the entries, with the
Xauthors' names removed.  Everyone then has a chance to vote and
Xcomment on the clues by sending e-mail to the moderator.  You do not
Xhave to enter to vote.
X
XThe moderator counts the votes and announces the winners.  The winner
Xof this contest is invited to moderate the next contest.
X
XThe moderator does not enter and does not vote, except to break ties.
X
XENTRY FORMAT
X
XYour entry should contain:
X  1) Your clue.
X  2) A detailed explanation of your clue.
X  3) Your e-mail address somewhere in the header.
X  4) Whether or not you can moderate the next contest.  Note: the
X     moderator's kit includes some shell/awk scripts for tabulating
X     the results.  If you don't have a Unix system, moderating this
X     contest will be a little awkward.  Some people have volunteered
X     to run these scripts for moderators on non-Unix systems.
X
XPlease use the form below for submitting your entry.  This will make
Xthe moderator's job easier.
X
X======== cut here ========
XHere's my clue.  I hope it wins.
X----------------
XEntrant: <<<your name>>> <<<e-mail address is optional here>>>
X<<<your clue comes here>>>
X
X	<<<your explanation comes here, each line indented by a tab>>>
X----------------
XI <<<can|can't>>> moderate the next contest.
X======== cut here ========
X
@@@End of announcement
echo x - comments 1>&2
sed 's/^X//' >comments <<'@@@End of comments'
X#! /usr/bin/perl
X# or could be /usr/local/bin/perl
X# script to sort comments
X# usage: comments FILE1 FILE2 ... FILEN
X# output will go to comment.N where N is the clue #
X# all input can be from just one file, e.g. a mailbox folder
X#
X$pref = "comment";
Xwhile (<>) {
X    if (s/^(\d+)\) ?//) {  # grab and delete leading number
X      $out = "$pref$1";
X      if ($open ne $out) {
X   print FH "\n" if ($out); # blank line separator
X   close (FH);
X   open (FH, ">>$out");
X   $open = $out;
X      }
X      print FH $_;
X    }
X}
Xclose (FH);
X
@@@End of comments
echo x - how-to-vote.numerical 1>&2
sed 's/^X//' >how-to-vote.numerical <<'@@@End of how-to-vote.numerical'
XSubject: PCWC ?? voting instructions
X
XThe entries for PCWC ?? are listed below.
X
XNow it's time for everyone to vote for their favorite clues.  Anyone
Xis allowed to vote (except the moderator).
X
XThe moderator:             ????????????
XThe schedule:
X  ?? ????ember 23:59 ??T   Deadline for votes
X  ?? ????ember             I'll post the results
X
XTo vote, read through the clues and their explanations, and rank the
Xclues on whatever linear scale you choose.  Votes will be normalized
Xto a scale from 0 to 100 -- that is, the lowest score that you assign,
Xwhatever it is, will become 0 and will be taken as meaning the worst
Xclue, and similarly the clue you rate highest will score 100.
X
XYou don't need to vote on every clue.  For any clue that you skip,
Xits score will be determined by those people who do vote on it.
X
XThe format for ballots is described below.  If you don't adhere strictly
Xto the format, it will create extra work for the moderator.  E-mail your 
Xballots to the moderator before the deadline.  Please, no campaigning, 
Xand only one vote per person.
X
XBALLOT FORMAT
X
XThis is a sample ballot:
X----------------------------------------------------------------
X1 = 9.99
X1) This was a wonderful clue because, well, I always really
X1) like whichever clue is listed first.
X
X2 = 9.99
X3 = 3.14
X3) I hated this clue because I read it after coming back
X3) from lunch and I hate coming back from lunch.  Next
X3) time remind me not to read your clue after lunch.
X
X-1) I always like reading bonus clues.
X
X0) This was a fascinating set of clues, and the moderator must be
X0) a truly wonderful and gifted person for choosing so fine a word.
X----------------------------------------------------------------
X
XThere are two types of lines, which can appear in any order.
X
XThe first type of line is for ratings.  The format is:
X
X	clue# = rating
X
XPut each clue/rating on a separate line.  The lines don't have to be
Xin numerical order, and as noted above, you don't have to rate every
Xclue.  The rating can be any decimal number.  The final score for each
Xclue will be the average (mean) of all the ratings that it receives,
Xafter normalization. 
X
X***NB Please note that the equal sign '=' must be
Xpreceded and followed by at least one space.
X
XThe second type of line is for comments.  The format is:
X
X	clue#) commentary
X	clue#) commentary
X
XEVERY LINE of comments must be preceded by the clue number.  Comments
Xwill be reported in the PCWC results, anonymously unless you choose
Xto identify yourself within them.  You don't need to comment at all
Xif you don't want to, but most clue writers do appreciate comments.
X
X***NB Please note that there must be at least one space character 
Xbetween the right bracket and the comment.
X
XClues that are actual contest entries have positive numbers, from 1 up.
XBonus clues have negative numbers, from -1 down -- comment on them if
Xyou wish, but there is no voting.  Finally, you can comment on the
Xcontest as a whole by putting 0 for the clue number; these remarks
Xwill appear at the top of the results posting.
X
XBlank lines are ignored.
X
X***NB Please note, the dash separators around your ballot are mandatory.
XThey must begin with at least eight consecutive hyphens.
X
X
XALL CLUES WITHOUT EXPLANATIONS
X
X????????????????????????????????????????????????
X???? <- Insert a control-L here if you can
X
XALL CLUES WITH EXPLANATIONS BY THE AUTHORS
X
@@@End of how-to-vote.numerical
echo x - how-to-vote.ranking 1>&2
sed 's/^X//' >how-to-vote.ranking <<'@@@End of how-to-vote.ranking'
X        PCWC # Ballot
X
XThe clues for PCWC # are all in; it's time to vote for your favorites.
X(Both clue submitters and non-submitters are allowed to vote.)  The
Xremaining relevant dates for PCWC # are:
X
X  ????day   19 ???ober 23:59 ??T   Deadline for receipt of PCWC # votes
X  ????day   20 ???ober             I'll post an annotated list of the
X       best-loved clues for PCWC #.
X
XThis post is divided into three parts.
X
X 1) a list of all the clues for the word without explanations
X 2) the same list annotated with the author's explanations
X 3) instructions on how to vote, and on the scoring
X
X------------------------------------------------------------------------
X
XALL CLUES WITHOUT EXPLANATIONS
X
X 1) ???????????????
X
X 2) ???????????????
X
X???? <- Insert a control-L here if you can
X
XALL CLUES FOR '??????????' WITH AUTHORS' EXPLANATIONS
X
X 1) ???????????????????????????????????
X
X      ??????????????????????
X      ?????????????????????
X
X------------------------------------------------------------------------
X
X 2) ???????????????????????????????????
X
X      ??????????????????????
X      ?????????????????????
X
X------------------------------------------------------------------------
X
XVOTING:
X
XIn this posting all the submitted clues are identified by a single
Xnumber.  To vote, send me a piece of Email that looks something like
Xthis:
X
XKind moderator,
X
XHere's how I felt about the entries to PCWC #
X
X---------------------------------------------
X3 7
X5 4 1
X8 2 6
X---------------------------------------------
X
X  E. Pluribus
X
X  e@pluribus.unum.edu
X
X
XThis specifies a partial ranking of the clue numbers, with
X
X3 = 7 > 5 = 4 = 1 > 8 = 2 = 6
X
XThe first line contains the numbers of the clues you like best; the
Xsecond line those you like second best, etc.  Within a line, list
Xclues numbers that you like about equally well in any order.  Any clue
Xnumbers that don't appear in your ranking will be added at the end on
Xa line by themselves; all equal and worse than any that you did list.
XThe number of lines is up to you: if there are 10 clues, for example,
Xyou can have up to ten lines.  If you are lazy, you can just send me
Xa single number of the clue you like best; note, however, that the
Xgreater an effort you make to differentiate between all the clues, the
Xmore accurate the results will be.  If you list a number more than once,
Xyou will be sent to the farm, immediately.
X
XPlease note that the lines with clue numbers in your voting should be
Xbracketed by lines with only dashes, to facilitate automatic
Xtabulation of the scores.  Do not put any other dashes in your ballot.
X
XBoth clue submitters and non-submitters are allowed to vote.  You ARE
Xallowed to vote for your own clue, but please try to be honest.  Of
Xcourse, one vote per person; DON'T use multiple accounts or aliases to
Xstuff the ballot box or encourage your cronies and cohorts to vote for
Xyour clue just so you can win.
X
XShould you wish to make critical comments regarding any or all of the
Xclues, your comments will be posted anonymously with the PCWC results
Xprovided that you precede *each* line of your comments with the clue
Xnumber and right parenthesis, as in the following examples:
X
X1) This was a wonderful clue because, well, I always really
X1) like whichever clue is listed first.
X
X2) I hated this clue because I read it after coming back
X2) from lunch and I hate coming back from lunch.  Next
X2) time remind me not to read your clue after lunch.
X
X
XSCORING:
X
XThe scoring will be as in tournaments, with 1 point for each better
Xranking and 1/2 point for a tie.  So, for example, based only on the
Xvotes of E. Pluribus above, the scoring (assuming there were 8 entries)
Xwould be
X
XClue  Pts.
X 1     4
X 2     1
X 3     6 1/2
X 4     4
X 5     4
X 6     1
X 7     6 1/2
X 8     1
X
XThe total scores will be the sum of the scores from all voters.  The
Xmoderator does not vote.
X
@@@End of how-to-vote.ranking
echo x - score.numerical 1>&2
sed 's/^X//' >score.numerical <<'@@@End of score.numerical'
X#!/bin/sh
X
X# score.numerical
X
X# The first file named must be a list of clues and authors.  In this file,
X# EACH LINE of each clue must begin (after possible whitespace) with the
X# clue number and a ")".  The author lines must begin (after possible
X# whitespace) with the clue number, whitespace, and "Entrant:".
X
X# The other files must each contain a list of votes, with a line of dashes
X# preceding and following the votes.  Each vote is a clue number, an "=",
X# and a numerical score, delimited by whitespace.  The file may also
X# contain comments, with the same syntax as the clues in the clue file.
X
X# This code was deliberately written to use a small set of the features of
X# the shell and the various programs called, by way of maximizing portability
X# even in the face of nonportabilities that I was not aware of.  For instance,
X# neither sh nor awk functions are used, and there are no continuation lines
X# in the awk code.  Feel free to enhance or debug this code, but please try
X# not to reduce portability.
X#     Mark Brader, January 1, 1994
X
X## Quick addition to allow general comments on the contest by preceeding
X## them with "0)", added by Ilana Stern July 1994.
X##
X## Further addition to properly handle bonus clues by giving them negative
X## clue numbers, by Mark Brader, April 21, 1997.
X
X
X# Check out the arguments and the contents of the clue file,
X# and provide for tempfiles
X
Xcase "$#" in
X[01]) echo "Usage: $0 cluefile votefile ..." >&2
X   exit 1
Xesac
X
Xseparator='-------------------------------------------------------------------'
Xtab='	'
Xnewline='
X'
Xerror=sc$$e
Xclean=sc$$c
Xtable=sc$$t
Xtrap "rm -f $error $clean $table; exit" 0 1 2 3 15
X
Xcluefile=$1
Xshift
X
Xtr "$tab" " " <$cluefile |
X   egrep -v '^ *$|^(- *| *)[0-9][0-9]*[)]|^(- *| *)[0-9][0-9]*  *Entrant' \
X      >$error
X
Xif test -s "$error"
Xthen
X   echo "Unrecognized line(s) in file $cluefile of clues and authors:"
X   cat $error
X   exit 1
Xfi
X
X
X# Normalize the vote files
X
Xfor votefile in $*
Xdo
X   # Select from one line of dashes to the next in each vote file
X   sed -n '/^--------/,/^--------/s/^ *//p' $votefile |
X   tr "$tab" " " |
X
X   # Classify each line, and check for conflicting votes
X   awk '
X   BEGIN  { null = 1 }
X   /^$/   { next }
X   /^--------/ { next }
X   /^[0-9][0-9]*[)] / { next }
X   /^-[0-9][0-9]*[)] / { next }
X   /^-[0-9][0-9]*  *=  *-*[0-9][0-9.]* *$/ {
X      print "File '$votefile': vote on bonus clue", $1, "ignored"
X      next
X   }
X   /^[0-9][0-9]*  *=  *-*[0-9][0-9.]* *$/ {
X      clue = $1 + 0
X      vote = $3 + 0
X      null = 0
X      if (found[clue]) {
X         if (score[clue] != vote) {
X            # We cannot delete from an array in awk, so use a magic value
X            score[clue] = "ignore"
X            print "File '$votefile': conflicting votes on clue",clue,"ignored"
X         }
X      } else {
X         score[clue] = vote
X         found[clue] = 1
X      }
X      next
X   }
X      {
X      print "File '$votefile': unrecognized line:", $0
X   }
X
X   #  Normalize the votes on a scale of 0 to 100
X   END {
X      if (!null) {
X         null = 1
X         for (clue in score) {
X            if (score[clue] != "ignore") {
X               if (null) {
X                  null = 0
X                  lo = score[clue]
X                  hi = score[clue]
X               } else {
X                  if (lo > score[clue]) lo = score[clue]
X                  if (hi < score[clue]) hi = score[clue]
X               }
X            }
X         }
X      }
X      if (null) print "File '$votefile': no valid votes found"
X      else if (lo == hi) print "File '$votefile': all votes equal!"
X      else {
X         for (clue in score) {
X            if (score[clue] != "ignore") {
X               print "=", clue, 100 * (score[clue] - lo) / (hi - lo)
X            }
X         }
X      }
X   }'
Xdone >$clean
X
X# We can't write to stderr from inside awk code, so we flag the
X# valid lines with a leading "=", and any OTHER line is a diagnostic.
X# Such diagnostics are nonfatal, so we print them here to stderr
X# and keep going.
X
Xgrep -v '^=' $clean >&2
X
X# Grab the comments for the contest in general
X
Xecho $separator
Xecho $separator
Xecho
Xecho "Overall Comments on the Contest"
Xecho
Xecho $separator
Xecho
Xfor votefile in $*
X  do
X    sed -n "/^ *0)  */s///p" $votefile | sed '$G'
X  done
Xecho
Xecho
X
X# Now add up the votes for each clue and produce an average score.
X# We also sort the clues according to their scores.
X
Xecho $separator
Xecho $separator
Xecho
Xecho "Results of the Voting"
Xecho
X
Xawk '
XBEGIN  { null = 1 }
X/^=/   {
X   clue = $2
X   votelist[clue] = votelist[clue] " " (int($3+0.5))
X   points[clue] += $3
X   votes[clue]++
X   if (null) {
X      null = 0
X      hiclue = clue
X   } else {
X      if (hiclue < clue) hiclue = clue
X   }
X}
XEND   {
X   if (!null) {
X      for (clue = 1; clue <= hiclue; ++clue) {
X         if (votes[clue]) {
X            score = points[clue] / votes[clue]
X            list = votelist[clue]
X         } else {
X            score = 0
X            list = " none"
X         }
X         printf "%6.2f%% %3d %s\n", score, clue, list
X      }
X   }
X}' <$clean | sort -r >$table
X
Xhiclue=`wc -l <$table | sed 's/ //g'`
Xcase $hiclue in
X0) echo "No valid data found at all!" >&2
X   exit 1
Xesac
X
X# Check the clue numbers in the vote files against the clue file
X
Xsed -n "/^[ $tab]*"'0*\([1-9][0-9]*\)[)].*/s//\1/p' $cluefile | sort -n -u |
Xawk '
X   $1 != NR {
X      print "Clue file '$cluefile' omits clue", NR "!"
X      exit
X   }
X   NR > '$hiclue' {
X      printf "%6.2f%% %3d %s\n", 0, NR, " none"
X   }
X   END {
X      if (NR < '$hiclue') {
X         print "Clue file '$cluefile' omits clue", NR+1 "!"
X         exit 1
X      }
X   }' >$error
X
X# Report any missing clues, but continue
X
Xgrep -v % $error >&2
X
X# If the highest-numbered clue(s) weren't voted on, add them to the
X# table now, and recompute the highest clue number.
X
Xgrep % $error >>$table
Xhiclue=`wc -l <$table | sed 's/ //g'`
X
X# Compute how many clues to identify by the submitter's name
X
Xleaders=`echo $hiclue | awk '{print int(($1+2)/3)}'`
X
X# Now add bonus clues to the table also
X
Xsed -n "/^[ $tab]*"'-0*\([1-9][0-9]*\)[)].*/s//-\1/p' $cluefile |
X   sort -n -u -r | sed 's/.*/bonus & none/' >>$table
X
X
X# Add rank labels to the scores
X
Xawk '{
X   if ($1 != prev) {
X      prev = $1
X      rank = NR
X      # Ah, the English language...
X      units = rank % 10
X      suffix = "th"
X      if (rank % 100 != units + 10) {
X         if (units == 1) suffix = "st"
X         if (units == 2) suffix = "nd"
X         if (units == 3) suffix = "rd"
X      }
X   }
X   print rank, suffix, $0
X}' <$table |
X
X# Strip multiple spaces, because the read command in some sh
X# versions uses a single space as the delimiter
X
Xsed 's/   */ /g' |
X
X# And turn each line of the score table into a report on that clue
X
Xwhile read rank suffix score clue votelist
Xdo
X   case $score in
X   bonus)
X      case $onbonuses in
X      y) ;;
X      *) onbonuses=y
X         echo $separator
X         echo $separator
X         echo
X         echo "Comments on the Bonus Clues"
X         echo
X      esac
X   esac
X
X   echo $separator
X   echo
X
X   # The clue's rank and score
X   case $onbonuses in
X   y) echo "Bonus clue $clue";;
X   *) echo $rank$suffix place '('score $score')' - clue $clue
X      if test $rank -le $leaders
X      then
X         sed -n "/^[ $tab]*0*$clue  *Entrant:*[ $tab]*/s//Entrant /p" $cluefile
X      fi;;
X   esac
X   echo
X
X   # The clue and its votes
X   sed -n "/^[ $tab]*0*$clue)[ $tab]*/s//    /p" $cluefile
X   case $onbonuses in
X   y) ;;
X   *) echo
X      echo "Votes (normalized): "`
X         echo $votelist | tr " " "$newline" | sort -n`;;
X   esac
X
X   # And the comments on the clue from each votefile
X   echo
X   for votefile in $*
X   do
X      # Match the clue even if leading zeros given in votefile
X      cluewithzeros=`echo "$clue" | sed 's/[0-9]/0*&/'`
X      sed -n "/^ *$cluewithzeros)  */s///p" $votefile | sed '$G'
X   done
Xdone
X
Xecho $separator
Xrm -f $error $clean $table # paranoia in case trap 0 fails in some stupid sh
@@@End of score.numerical
echo x - score.ranking 1>&2
sed 's/^X//' >score.ranking <<'@@@End of score.ranking'
X#!/bin/sh
X
X# usage:
X#
X# score N votefile1 votefile2 votefile3 ....
X#
X#   where N is the number of total number of clues and each votefile
X#   contains one piece of mail with votes.  Recommended procedure is
X#   to place all the vote mail in a single directory and do
X#   score N *
X
X(NCLUES=$1
Xecho NCLUES $NCLUES
Xshift
Xfor foo in $*
Xdo 
X   echo FILE $foo
X   sed '1,/----/d;/----/,$d' $foo
X   echo EOF
Xdone) | awk '
X/NCLUES/ {nclues = $2}
X/FILE/  {fname = $2}
X/^[0-9 \t]*$/ {
X       nok = 0
X       for (i = 1; i <= NF; i++)
X    if ($i < 1 || $i > nclues)
X        printf ("Bogus clue #%d in file %s ignored\n", $i, fname)
X    else if (seen[$i] > 0)
X        printf ("Duplicate clue #%d in file %s ignored \n", $i, fname)
X    else
X        seen[ok[nok++] = $i]++
X       sofar += nok
X       for (i = 0; i < nok; i++) {
X    s = nclues - sofar + (nok - 1) / 2
X    score[ok[i]] += s
X    sumsq[ok[i]] += s * s
X    m = ++hist[int(2 * s) * nclues + ok[i] - 1]
X    if (m > maxhist)
X       maxhist = m
X       }
X      }
X/EOF/ {
X       nvoters++
X       for (i = 1; i <= nclues; i++)
X    if (seen[i] == 0) {
X       s = (nclues - sofar - 1) / 2
X       score[i] += s
X       sumsq[i] += s * s
X       m = ++hist[int (2 * s) * nclues + i - 1]
X       if (m > maxhist)
X    maxhist = m
X      } else
X       seen[i] = 0
X       sofar = 0
X }
XEND {
X       printf ("\nThere were %d clues and %d voters; ", nclues, nvoters)
X       max = nvoters * (nclues - 1)
X       printf ("maximum total %.1f\n\nScores:\n\n", max)
X       printf ("\tClue\ttotal\t %%max\trank\t  mean\t st.dev\t median\n")
X       printf ("\t----\t-----\t ----\t----\t  ----\t ------\t ------\n")
X       for (i = 1; i <= nclues; i++) {
X    avg = score[i] / nvoters
X    dev = sqrt (sumsq[i] / nvoters - avg * avg)
X    rank = 1; ties = -1
X    for (j = 1; j <= nclues; j++)
X        if (score[i] < score[j])
X     rank++
X        else if (score[i] == score[j])
X     ties++
X    med = 0; s = -1; k = 0;
X    for (j = 1; j <= nvoters; j++) {
X        while (k == 0)
X    k = hist[++s * nclues + i - 1]
X        --k
X        if (j == int ((nvoters + 1) / 2))
X     med += s / 4
X        if (j == int (nvoters / 2) + 1)
X     med += s / 4
X    }
X    printf ("\t%3d\t%5.1f\t%5.1f\t", i, score[i], score[i] * 100/max)
X    if (ties)
X        printf ("%2d-%d", rank, rank + ties)
X    else
X        printf ("%3d", rank)
X    printf ("\t%6.2f\t%6.2f\t%6.2f\n", avg, dev, med)
X       }
X       printf ("\nVote distribution histograms:\n\n")
X       for (i = 1; i <= nclues; i++) {
X    for (n = maxhist; n > 0; --n) {
X        printf ("%12d |", n)
X        for (s = 0; s <= 2 * (nclues - 1); s++)
X    if (hist[s * nclues + i - 1] >= n)
X        printf ("X")
X    else
X        printf (" ")
X        printf ("\n")
X    }
X   printf ("Clue #%-7d|", i)
X   for (s = 0; s <= 2 * (nclues - 1); s++)
X       printf ("_");
X   printf ("\n              ")
X   for (s = 0; s <= 2 * (nclues - 1); s++)
X       if (s >= 20 && s % 2 == 0)
X    printf ("%d", s / 20)
X       else
X    printf (" ")
X   printf ("\n              ")
X   for (s = 0; s <= 2 * (nclues - 1); s++)
X       if (s % 2 == 0)
X    printf ("%d", (s / 2) % 10)
X       else
X    printf (" ")
X   printf ("\n\n")
X       }
X      }
X'
X
@@@End of score.ranking
echo x - shuffle 1>&2
sed 's/^X//' >shuffle <<'@@@End of shuffle'
X#!/usr/bin/perl
X
X# Usage: shuffle [FILE ...]
X#
X# Given input that contains "sections" separated by dashes, like
X# --------------
X# section 1
X# ----------
X# section 2
X# ------------
X# etc.
X# write the sections to stdout in random order, separated with dashes.
X
X@entries = ();
X
X&read();
X&shuffle();
X&print();
X
X
Xsub read {
X local ($this) = '';
X
X sub add_entry {
X  push(@entries, $this) if $this ne '';
X  $this = '';
X }
X
X while (<>) {
X  if (/^----+$/) {
X   &add_entry();
X  } else {
X   $this .= $_;
X  }
X }
X &add_entry();
X}
X
X
Xsub shuffle {
X local ($j, $k);
X
X srand();
X for ($k = 1; $k < @entries; ++$k) {
X  $j = int(rand($k));
X  @entries[$j, $k] = @entries[$k, $j];
X }
X}
X
X
Xsub print {
X local ($line) = ('-' x 40) . "\n";
X
X print $line;
X for ($k = 0; $k < @entries; ++$k) {
X  print $entries[$k];
X  print $line;
X }
X}
@@@End of shuffle


