UseVote V3.0 - Usenet News Group Voting Software by rdippold@qualcomm.com For the latest versions of UseVote by anonymous ftp: Thanks to Dave Lawrence, at ftp.uu.net under networking/news/misc/usevote. Thanks to Dave Cornejo, at netcom.com under /pub/dnc. Thanks to Christophe Wolfhugel, at grasp.insa-lyon.fr under /pub/unix/news/tools. --------------------------------- LEGAL ---------------------------------- (c)1993, 1994 Ron Dippold All Rights Reserved Distribute freely, use freely, please notify me of any nifty improvements you make, and please distribute the entire package including all source code and all docs. And I'd appreciate it if you let me know when you run a vote with it, and any comments you have. UseVote should be relatively bug free, and bugs tend to get reported quickly. However, I'm not responsible for anything that happens when you run this. You assume all risk. This paragraph is here because lawyers can be scum. -------------------------- BRIEF DESCRIPTION ----------------------------- UseVote takes a lot of pain out of a painful process - running a Usenet Newsgroup Vote. Single item votes aren't all that bad, although they're a lot of cut and paste, but multiple-item votes are a real bear. This software, which was written for the comp.sys.ibm.pc.games reorganization, and later improved for general release as others showed interest, made the whole process easy and far less error-prone. It doesn't abolish all human interaction - you'll still have to do some work. But it makes it manageable. This also works for any yes/no ballot, although it wasn't designed for that. The programs in UseVote are all written in very portable C - they compile on our Sun, which has a very conservative C compiler, and should compile on almost anything. Let me know if it doesn't! ------------------------------ FILE LIST ----------------------------- There should be a bundle of files: README This file - the docs WHATSNEW Version changes acktext.txt Text for acknowledgement letters to voters blurb Basically, a quick summary of UseVote cfv Sample CFV to run through uvcfv. convert.c Convert old results files to new ones makefile The make file for compiling the software newvote Make a new vote if you're running several sample.cfv A sample CFV for single group ballot sample2.cfv A sample CFV for multiple group ballot sampvote Sample votes that work with included usevote.h usevote.cfg Configuration file for individual vote usevote2.cfg Sample configuration file for multiple group vote usevote.h Configuration info for your system usevote.rul Voting rules file uvack.c Make voting acknowledgement lists uvballot.c Generate ballot from your vote data uvbounce.c Generate Mail Ack bounce lists uvcfv.c CFV massager - see uvcfv.doc uvcfc.doc Docs for uvcfv.c uvconfig.c Read configuration shared module uvcount.c Give a total vote count for each group uvdup.c Detect duplicate votes uvshell Unix "sh" script to automate uvvote further! uvvote.c Process votes -------------------- INITIAL CONFIGURATION ------------------------------- The first thing you need to do is edit "usevote.h". This should contain everything that you need to configure UseVote for your specific system. Now compile the uv*.c files. You need to do this any time you change usevote.h or thisvote.h. The programs are written in very portable C, so they should compile on almost any machine (cross fingers). Each of the files needs the module uvconfig.c, which reads the configuration for that vote. You'll need to compile the following: uvack.c Make voting acknowledgement lists uvballot.c Generate ballot from your vote data uvbounce.c Generate Mail Ack bounce lists uvcfv.c CFV massager uvcount.c Give a total vote count for each group uvdup.c Detect duplicate votes uvvote.c Process votes On most Unix machines the compile command is: cc uvack.c uvconfig.c -o uvack For Mickeysoft C it should be: cl /AL uvack.c uvconfig.c Repeat for each file... I've included a "makefile" command which has a good chance of working under a Unix system. Just "make". If they don't compile, you need to mail me and tell me exactly what happened. What version, which file, what line, what error message, etc. Note that some compilers don't like the "#include " lines, but will still work if you remove those lines from all the .c files. With luck, you can now use these executables for any vote you want to run. I suggest you keep them in one place and set up a link to them from each voting directory. The next thing to change is "acktext.txt". You'll need to update it for your name and address, and any individual wording preference. ----------------- Special: USING sendmail OR smail ----------------------- Some people will prefer using sendmail at their site rather than mail. The MAILCMD in usevote.h is very powerful... you can set it up to do use almost any mail command. Here's one from Ian Kluft which uses sendmail. The "formail" filter is from procmail 2.8, but any filtering script should do. You can add any header you want by just adding another -A \"Myheader: value\". This will work with smail as well. The -odq sends mail in the "queue only" mode, which means you can get rid of those "sleep 20"s. #define MAILCMD "/bin/echo \"From ikluft@amdahl.com\\n\" | /bin/cat - #f | /usr/local/bin/formail -A \"To: #v\" -A \"Subject: #s\" -A \"From: ikluft@amdahl.com (Ian Kluft)\" -A \"Errors-To: ikluft@amdahl.com (Ian Kluft)\" -A \"X-Automated-Message: generated by UseVote 2.2x\" | /usr/lib/sendmail -odq #V && rm #f" If you have any problems with this, turn the #V into a \"#v\" ------------------- INDIVIDUAL VOTE CONFIGURATION ---------------------- Each vote needs its own configuration file. Edit "usevote.cfg" for the specifics of your vote. If you're going to be running a multiple item vote, I suggest you copy "usevote2.cfg" to "usevote.cfg" first, as it is set up closer to optimum for that. The comments in the files should be fairly self-explanitory. I'll just comment a bit more on VOTEMARK... this will be used in the ballot, and the text in it should not appear ANYWHERE ELSE in the cfv. It's traditional to issue a first CFV, then two more CFVs during the voting period, because people miss it, procrastinate, whatever. The '%' in VOTEMARK will be replaced by the number of the CFV - in this way, you can see by looking at the returned ballot just which of the CFVs this vote was returned from. Just make VOTEMARK some unlikely combo, like "" for rec.arts.prose. The first two zeros are just for show, but don't they look impressive? The final item to check is "usevote.rul". If your vote has any special voting rules, such as that you can only vote on group x if you voted on group y, or that if you vote yes on any part of a split you must vote yes on the .misc group, then you will need to read "usevote.rul" and add your own rules. Now you can test your setup by running "uvvote -t" -------------------------- GENERATE BALLOTS ------------------------------- * FOR SINGLE ITEM VOTES * Look to the sample.cfv file to see how to do it. Basically, you tell the voters to include only one of the following in their return message: I vote YES on rec.foo.bar I vote NO on rec.foo.bar This way, they can just uncomment the one they don't want, and as a bonus, this will handle the situation where some people insist on placing this information in the Subject: line. All it needs is the the group name, and one of the yes/no/for/against keywords. Note that UseVote will also handle CANCEL and ABSTAIN votes. ABSTAIN votes don't count in the final creation decision, but are useful as a symbolic gesture. They're very useful in multiple group votes, where you might not want to vote on everything, that's why UseVote has them. CANCEL votes will cancel previous votes and will not show up in any ack list. See sample.cfv for how to present these. * FOR MULTIPLE ITEM VOTES * You need to write your CFV and put the ballot in it. I have included, in "sample2.cfv", some sample text to be included just before the ballot itself. Voters really need to be lead by the hand. Now, generate the ballot: uvballot 1 This generates the ballot for the first cfv. Later, as you do your 2nd and 3rd CFVs, you can "uvballot 2" and "uvballot 3". This will show you what it will look like, a good test of your configuration. If things look okay, redirect the output to a file: uvballot 1 > temp Now you can edit this into your cfv. WARNING: Try to avoid using a group name and any of the keywords (for, against, yes, no, abstain, cancel) in a single line in any text after the ballot. There is currently no end of ballot marker, and if some idiot returns the entire CFV instead of just the ballot, that line could be treated as a vote. --------------------------- SAVING BALLOTS -------------------------------- Note: if you're running several votes, I have a utility, uvsplit, which will handle the chore of separating the votes into their appropriate directories. It should be available in the same places as UseVote. Returning ballots need to be saved to their own file - you can use the "copy" command in my mail reader. Whenever you see the "comp.sys.ibm.pc.games reorg" subject have a macro do a "move votes". In your mail program it may be "file" instead of copy. If you're going to be doing a bounce ack list (a list of all mail acks that have bounced), save those to a separate file, such as "bounce". Alternatively, you can set up a separate address for the votes. I do this, then use a mail filtering program (deliver) to automatically place the votes in a separate voting file. ------------------------ PROCESSING VOTES ------------------------------ Big hint: If you're using Unix and have the "sh" shell available, you might want to check out "uvshell" - it'll take care of all this crud! Otherwise, read on. So, you've got these votes in a file. Move the file of votes to a UNIQUE file name (don't copy over old votes). Then do a uvvote on the file: move votes votes2 uvvote votes2 result2 trace This will take the votes from file "votes2". All the results will be placed in the file "result2". Do NOT give the name of any file that contains anything useful for the results file, especially any other voting results. Anything in result2 will be overwritten. The "trace" file is optional. If you specify it, a helpful dump of relevant info from the process will be save to that file, and you can look at it for any strangeness. If you chose to generate vote acks (and you really should, unless you have a darn good reason), it will create a series of "ack." files: "ack.aaa", "ack.aab", "ack.aac", etc. All the way up to "ack.zzz" if necessary. This lets you process 4095 votes in a single go. It also generates a file called "domail" which will actually mail all these suckers out. You may need to change it to an executable type file with a chmod 700 domail before you can run it. Once you run domail, you can delete it and all the "ack.???" files. If you've defined VOTEACKCLEAN in "usevote.h" all the acks will automatically be cleaned out. I do this as a separate process so that if something comes up you can fix it before any acks go out. Note on "domail": on some systems, every piece of mail sent will result in a separate mail process being created. If you have a lot of acks to send, that's a lot of mail, and can bog down those systems. Check your "mail" help file, the name of the option is often named "sendwait." In most systems it's not a problem, though. If you get any errors during the processing, usually becuase a ballot can't be found in a message, the person whose message generated the message will be sent a "couldn't process your ballot" message. If you do not want this to occur in a specific instance, you'll have to remove them from "domail" before you run it. Now you have two files - your mail votes file, and your results file. Save them. You don't really HAVE to save your votes file, but it's the safest thing to do, and they don't take up too much space when they're packed. Regardless, once you have your results you need to CLEAR your whatever mail votes file you're using (in case you're COPYing instead of MOVEing) so the votes won't be recounted again. I number everything sequentially like this: move votes4 done/votes4 move results4 done/results4 gzip done/votes4 Whatever you do, DON'T ACCIDENTALLY WRITE OVER YOUR OLD RESULTS FILES! The results files are what all the other programs operate on - they contain the name and address of each voter and how they voted. If you do accidentally delete or overwrite them, you can "uvvote" on the mail vote files you saved. You did save them, right? So, to summarize: * save votes in a file from mail over a period of time * move the file to a unique votefile name * "uvvote " * read the trace file * "domail" * save the votes and results files with unique names. You can automate most of this if you want. * ON HANDLING ERRORS IN THE PROCESSING * With UseVote 1.1, things got a lot more automatic. It should find most possible errors and handle them correctly, including sending the correct mail to the offender. It will print a list of errors to the display during processing (which can be redirected elsewhere for saving), and will print the errors in the trace file as well. If you really want, you can run everything damn near on automatic and count on the error mail to fix any problems. I used to run UVVOTE on the voting file, then edit the voting file to correct any correctable errors (such as the bozo deleting the start of ballot tag), then run UVVOTE again. It's not a lot of effort. With UseVote 2.0, there's the interactive option - see below. Here are the possible errors UseVote handles: * Invalid account (like guest@foo.bar.com) * No ballot found in message. * Did not vote on any item - this is meaningless, and probably an error. * Voted in contradictory ways on a single item. * Votes violated your "usevote.rul" rules. * Bad STV vote choices --------------------- INTERACTIVE VOTE PROCESSING ---------------------- UseVote 2.0 added an interactive option to "uvvote". Invoke it with an initial "-i" parameter like: uvvote -i votes1 results1 trace When you run it like this, it will still cough up an error message when it encounters a bad ballot. However, it will then ask you *** C)ontinue, D)iscard, E)xamine [E]? Or, if the error is that the account is invalid, *** A)ddress ok, C)ontinue, D)iscard, E)xamine [E]? If you choose "C"ontinue, uvvote will continue as normal and do all the error processing for the ballot. "D"iscard is useful for messages that aren't really votes but got into the votes file anyhow - you want to just pretend you never got it. A Discarded vote doesn't appear in the results file, even as an error, and there is no mail ack sent. "A"ddress OK indicates to uvvote that the address really is valid and we should treat this is a valid vote. If you choose "E"xamine (or just hit enter), you will be taken to the interactive mode. The top part of the screen shows the ballot. The bottom part of the screen shows what uvvote thinks the name, address, and votes are for this ballot. Your options are: Q)uit - discard any changes, exit interactive mode S)ave - save any changes, exit interactive mode In both cases, UseVote will reprocess the ballot and you'll get the C)ontinue / E)xamine choice if it's still bad. A)ddress - change the address of the voter. This is useful for when a bozo includes an invalid return address or (gasp) UseVote can't parse some weird name/address syntax. N)ame - change the name of the voter. Ditto. V)ote - change the votes of the voter. This will show you the current vote for each group and will prompt you for Yes, No, or Abstain. Mostly useful for when they split the vote and the group name over multiple lines. Note: a '!' shown as the vote for a group means that there are multiple conflicting votes. D)own - move down a page into the vote. The unshown commands "=" and "+" will move you down just one line. U)p - move up a page of the vote. The unshown command "-" backs up just one line. The [xxx%] shown on the dashed line is an estimate of how much of the ballot is displayed. --------------------------- COMBINED RESULTS --------------------------- uvack, uvcount, and uvdup need all your results to work on. So you have to combine all your result files into one. I do the following: cat result???? > results.all Since I have all my files stored in "result0001", "result0002", etc., this concatenates them and saves them in "results.all". You can also do the same thing with an editor. This "results.all" file is what I will use in all the following examples. ------------------------- ELIMINATING DUPLICATES ------------------------ It's going to happen in every vote that you get duplicate votes from the same address. Lots of people forget that they voted and vote again (although doing a mail acknowledgement helps). Some people change their minds. And some people try to cheat by voting multiple times. Regardless, you have to delete duplicates. The generally accepted procedure is to delete the oldest duplicate, on the theory that the newwer vote represents a change of heart on some issue. You should run uvdup before any mass acks or vote acks. The syntax of uvdup is simple: uvdup () where is your current file of all voting results, and will be a file that contains the new voting results with duplicates removed. THEY SHOULD NOT BE THE SAME FILE. Whatever file you give for will be utterly annihilated. The same applies for , if you choose to give one. If so, then a list of all deleted duplicates is saved to . This is helpful for seeing what was axed. First, uvdup will sort the votes by address to look for duplicate addresses. It has a unique ability to pare addresses down to organization names when sorting. For instance, in the following address: rdippold@ren.qualcomm.com "rdippold" is my username, "ren" is my machine, "qualcomm" is my organization, and "com" is the organization type. Well, it's entirely possible that I move to another machine and vote as rdippold@stimpy.qualcomm.com and a straight compare wouldn't think they were the same person! So uvdup cuts them both down to rdippold@qualcomm.com for the purposes of comparing, and declares them equal. Once it's sorted the votes, it will show you any that it thinks are duplicates, like this: Old vote: A: rdippold@ren.qualcomm.com N: Ron "Asbestos" Dippold D: Thu, 12 Aug 1993 15:42:13 -0600 C: V: NN--YNY New Vote: A: rdippold@stimpy.qualcomm.com N: Ron Dippold D: Thu, 29 Jul 93 07:18:06 PDT C: V: NN--YYY And will ask you if you really want to delete the older vote. In this case you can see that they are definitely a duplicate vote. Furthermore, you can see that I've changed my mind on the vote for the 6th group. So say "Y" and the old vote will be eliminated. The reason uvdup asks is because it can be over-paranoid. It may occasionally find a duplicate where none exists, though that usually happens with names instead of addresses. If it finds a vote that is obviously a duplicate, for instance with the same name and last two domain parts, or with the exact same address, it will just delete the oldest one (or, if one is invalid, it will delete that one). After you've gone through the addresses, uvdup will sort by name and perform the same comparisons and questioning. It will just skip any votes where no name is known. Finally, it will write the file, containing just the non-duplicate votes. At this point you'll probably want to save the file and rename the file to whatever the file was named. Maybe not, but you want to do the final voter list and vote count on the NEW file, not the old one! NOTE: Mail gateways can get very tricky. UseVote will not detect that bvr1234%rfpc@wubba.foo.com and bvr1234@bozo.edu are actually the same voter. The second address is his more direct address, in the first he's used another gateway. If he uses his name with both accounts it will be picked up in that pass, but otherwise not. Keep in mind that this can happen. SPECIAL NOTE: If you insert a "-y" as the first parameter, as in: uvdup -y oldresults newresults tracefile Then uvdup will not ask you whether or not do delete possible votes but will do it automatically. This should NOT be your normal mode of operation. This is only provided for some very rare instances of crude vote checking. If you use "-n" as the first parameter: uvdup -n oldresults newresults tracefile Then uvdup will never delete a vote without asking you - this is the ultimate paranoid mode. ----------------------------- ACKNOWLEDGEMENTS ----------------------------- Acknowledgements have multiple purposes. 1) Generating a list of all voters (without how they voted) so that everybody can check whether their vote was recorded or not, and whether or not they voted. It is expected that when you do your 2nd and 3rd CFV that you WILL include one of these Mass Acks at the end of your CFV. However, you may NOT list how anyone voted, or the vote will be invalidated. So be careful. 2) Generating a list of all voters and how they voted for your voting results. This is not optional. It should go at the end of the results posting. Don't for get to run uvdup to get rid of duplicates, first! You don't want someone's vote in error to show up in the error list, even though they've already mailed in a corrected version. To generate a list of all voters without how they voted for a Mass Ack (2nd or 3rd CFV), do a uvack results.all and you'll get an alphabetically sorted list of all the voters and a separate list of all votes that were rejected. If you like the looks, then redirect it to a file so you can edit it into your CFV: uvack results.all > massack To generate a list of all voters AND show how they voted for the final voting post, do a uvack -v results.all and you'll get an alphabetically sorted list. There's a behavior that needs to be explained here. It's traditional in a single-item vote that you list all the yes voters, then all the no voters, then all the abstaining voters. So if your vote only has one item, this is the way it will be done. On the other hand, this would be impossible (or huge) with more than one item, so in this case everything is sorted as usual, but a list of the votes is placed at the right, like this: rdippold@qualcomm.com Ron "Asbestos" Dippold YYN-N-Y jbeam@whiskey.daniels.com NNN-YYY for each voter. The YN- at the end is that person's vote for each group in order, one character per vote (Y = yes, N = no, - = abstain ). Again, redirect this to a file to include in your CFV with uvack -v results.all > temp The built in sort routines of uvack are optimized for low memory usage, not for speed. They shouldn't be a slouch, but if you find them too agonizingly slow, the "-u" option is available, and will leave everything unsorted. You will need to sort the addresses with a program of your own, or people will get on your case. uvack -v -u results.all > temp And finally, for those who dislike the formatting of the names, you can force a more standard name printing with the "-n" option. If you do so, acks will look like this: rdippold@qualcomm.com (Ron "Asbestos" Dippold) YYN-N-Y jbeam@whiskey.daniels.com NNN-YYY -------------------------- BOUNCE ACKNOWLEDGEMENTS ---------------------- With the advent of programs that can guarantee that a Mail Ack will go out to voters when their vote has been tabulated, the use of Mass Acks is seen by many as wasteful. If you are going to be sending Mail Acks for every vote, you may want to consider using a Bounce Ack instead of a Mass Ack for additional CFVs. After you mail a Mail Ack off, if for some reason the mail cannot be delivered, it should be returned to you with an error message. Save all these to a separate file, such as "bounce", just as you did with votes. Then when you want to generate a bounce list, just run uvbounce bounce And you'll get a sorted list to include with your CFV. You still need to use "uvack" for the list of all voters and their votes for the results posting, but not for the 2nd and 3rd CFVs. It's fairly simple - just a list of sorted names and addresses to which your Mail Acks of VALID VOTES have bounced. It's smart enough not to print two acks with the exact same address. As with uvack, the "-u" option will leave the addresses unsorted, though this eliminates the duplicate detection. In case you were wondering, normal policy is that votes by accounts to whom Mail Acks vote should be counted. If a whole slew of acks to a domain fails, it might be of interest to investigate, but that's about it. NOTE: uvbounce looks for the "Voter address:" and "Voter name:" that "uvvote" puts in the Mail Acks. If you have changed the uvvote.c code you will need to change uvbounce.c as well. ----------------------- COUNTING NORMAL VOTES ---------------------------- For STV voting see the next section... Finally! You want to count some votes... run uvcount on your votes: uvcount results.all And you'll get something like this (numbers totally fabricated): comp.sys.ibm.pc.games reorganization results - 923 votes Yes No : 2/3? >100? : Pass? : Group ---- ---- : ---- ----- : ----- : ------------------------------------------- 123 34 : Yes No : No : comp.sys.ibm.pc.games.misc 456 92 : Yes Yes : Yes : comp.sys.ibm.pc.games.announce 789 12 : Yes Yes : Yes : comp.sys.ibm.pc.games.action 123 155 : No No : No : comp.sys.ibm.pc.games.flight-sim 532 338 : No Yes : No : comp.sys.ibm.pc.games.strategic 356 357 : No No : No : comp.sys.ibm.pc.games.adventure 12 127 : No No : No : comp.sys.ibm.pc.games.rpg 13 invalid votes Yes and No are the number of yes and no votes, obviously. Due to abstentions, they will probably not add up to the number of votes shown in the header for any given group. 2/3? indicates whether the group passed the 2/3 popularity test, which states that 2/3 of the votes must be for the group. >100? indicates whether the group passed the 100 vote interest test, which states that there must be 100 more yes votes than no votes. Pass? indicates if the group passed. It is Yes if both 2/3? and >100? The number of invalid votes is the number of votes that were recorded as being in error. See acktext.txt for possible errors. If you are running a single item vote only, you'll get a result that looks like this: | unmoderated group rec.food.drink.beer passes 331:51 | |There were 331 YES votes and 51 NO votes, for a total of 382 valid votes. | |For group passage, YES votes must be at least 2/3 of all valid (YES and NO) |votes. There also must be at least 100 more YES votes than NO votes. | |There is a five day discussion period after these results are posted. If no |serious allegations of voting irregularities are raised, the moderator of |news.announce.newgroups will create the group shortly thereafter. This is the verbose mode. You can always force the table mode by using the "-t" parameter with uvcount: uvcount -t results.all Again, just redirect the output to a temporary file so you can paste it into the final voting results: uvcount results.all > temp uvcount also provides you an instantaneous way to see at any time how the vote is doing (although as an ethical person you should not start canvassing for votes if anything is doing badly - this will invalidate the vote). NOTE: uvcount allows a "-d" option, which will use the date field of votes to figure out exactly when each group "passed" its vote and will print that out. Fun to see exactly how long it took. ------------------------ COUNTING STV VOTES ---------------------------- Single Transferable Vote (preference) voting is tricky. We run through the entire set of ballots and assign each ballot to the highest valid preference item given on the ballot. Initially this is all choices. Then, if any item has 50% of all the votes, it wins. If there is no item with this 50%, then the item with the lowest number of votes is declared invalid, and we again assign each ballot to the highest valid preference item given on the ballot. So if the first choice preference has been eliminated, it goes to the second choice. If no chosen items are left the vote goes to a "No Preference" category. Repeat until an item gets 50%. Note that "No Preference" can win. UseVote will show all its work for an STV. You may want to just give the results. When you do an STV, you might want to get a list of preferences instead of just a single winner. If you use the "-r" option, UseVote will eliminate the winner and start all over again. This gives you the second most popular item. Then that is eliminated too, and the vote is run over again. This is repeated until all items have been eliminated. Then UseVote prints a list of items in order of preference. The "-d" and "-t" options are meaningless for STV voting. ---------------------------- OVERALL ----------------------------------- That's it! Here's a quick hint to help you in overall use: * Before the CFV - Let me know you'll be using it and what version of the software you have - I may have a newer version - Update usevote.h for your configuration - Change usevote.cfg for your configuration - Change acktext.txt for your configuration - Change usevote.rul if you need voting rules - Compile all the uv*.c files - Play around to see that you understand how it works * Initial CFV - Write CFV - Include sample ballot instructions from sample.cfv - Compile all the uv*.c files - Generate ballot text with "uvballot 1" and include your CFV * All during voting period - Save votes in separate file. Do all the following every couple days. - Save any Mail Ack bounces to a separate file, "bounce". - MOVE (not just copy) the file to a unique name, say votes4 for the 4th time you've done this - Run uvvote on the votes: "uuvote -i votes4 result4 trace" - Save the votes file and the results file in a safe place. You may want to compress the votes file to save space. * For the 2nd CFV - use "uvballot 2" to generate the 2nd ballot, replace the old one in your CFV For Bounce Acks: - run "uvbounce bounce > temp" to generate a Bounce Ack into the file "temp". Add to the end of your CFV. For Mass Acks: - concatenate all your results file into one big one, results.all - use "uvdup results.all results.new" to eliminate duplicates - use "uvack results.new > temp" to generate a Mass Ack into the file "temp". Add that to the end of your CFV. * For the 3rd CFV ( if you have one! ) - Just like the 2nd, but use "uvballot 3" instead. - And delete the old Ack before you include the new one! * For the final results - Delete the old Mass Ack, voting instructions, and ballot from your CFV file - concatenate all your results file into one big one, results.all - run uvdup to detect any duplicates: "uvdup results.all results.new" - run uvcount to count the votes: "uvcount results.new > temp" and edit temp into the beginning of your CFV. - run uvack to generate a final vote ack with votes: "uvack -v results.new > temp" and edit the results into the end of your CFV. - I suggest you compress all the votes files and result files into one file, and back it up to tape or floppy, just in case anything ever comes up. ------------------------------- AND.... -------------------------------- That's it! Hope this is helpful. -- Ron Dippold rdippold@qualcomm.com