/// <summary>
        ///     Generates the PDF files for all ballots.
        /// </summary>
        /// <param name="outputFolder">The output folder.</param>
        /// <param name="bar">The progress bar.</param>
        /// <externalUnit/>
        /// <revision revisor="dev11" date="2/26/2009" version="1.0.8.0901">
        ///     Member Created
        /// </revision>
        /// <revision revisor="dev11" date="03/04/2009" version="1.0.8.1501">
        ///     Added progress bar support
        /// </revision>
        private void GeneratePdfFiles(string outputFolder, ProgressBar bar)
        {
            // a given paper ballot
            PaperBallot ballot;

            // the file name of every page (PDF file name)
            string[] files;

            // the pages to print for the current paper ballot
            List <int> pages = new List <int>();

            // set the progress bar if available
            // step is the progress value
            int step = 0;

            if (bar != null)
            {
                // each key corresponds to a ballot that is generated
                ProgressBar_SetMaximum(bar, this.dicBallots.Keys.Count);
            }

            foreach (KeyValuePair <PaperBallot, string[]> pair in
                     this.dicBallots)
            {
                ballot = pair.Key;
                files  = pair.Value;
                pages.Clear();
                for (int i = 0; i < files.Length; i = i + 1)
                {
                    if (!File.Exists(Path.Combine(outputFolder, files[i])))
                    {
                        // do not generate the same PDF twice. Each PDF is for
                        // just 1 page
                        pages.Add(i);
                    }
                }

                ballot.Draw(
                    outputFolder,
                    PaperBallot.GetPdfFilename(ballot),
                    pages.ToArray());

                // update progress bar if available
                if (bar != null)
                {
                    step = step + 1;
                    ProgressBar_SetValue(bar, step);
                }
            }
        }
        /// <summary>
        ///     Adds a ballot to the binder. This method identifies common
        ///     faces, so that they can be reused reducing the final set of PDFs
        /// </summary>
        /// <param name="ballot">The ballot.</param>
        /// <externalUnit/>
        /// <revision revisor="dev11" date="2/25/2009" version="1.0.8.0801">
        ///     Member Created
        /// </revision>
        public void AddBallot(PaperBallot ballot)
        {
            // get the faces of this ballot
            List <PaperFace> faces = PaperBallot.GetFaces(ballot);

            // get the filenames for all the faces of the ballot
            PaperFace face;

            string[] files = Pdf.CreatePdfFilenames(
                PaperBallot.GetPdfFilename(ballot),
                faces.Count);
            string md5, filename;

            // for each face, find it in the lookup dictionary. If it is found,
            // it means that an identical face has already been created, so
            // don't include it when generating the PDF files and replace the
            // filename for the exisiting one
            if (this.dicBallots.ContainsKey(ballot) == false)
            {
                // add the ballot to the dictionary along with its set of
                // file names
                this.dicBallots.Add(ballot, files);
            }

            for (int i = 0; i < faces.Count; i = i + 1)
            {
                // PaperFace <-->  filename
                // faces[0]  <-->  files[0]
                // faces[1]  <-->  files[1]
                // ...
                face     = faces[i];
                filename = files[i];
                md5      = BitConverter.ToString(ObjectMD5.Generate(face));
                if (this.dicFaces.ContainsKey(md5) == false)
                {
                    // this is a new face that up to this point no other ballot
                    // has, so add it to the dictionary for future comparison
                    // to subsequent ballots
                    this.dicFaces.Add(md5, filename);
                }
                else
                {
                    // an identical face is already in use, so to the current
                    // ballot assign that face and replace the duplicate
                    files[i] = this.dicFaces[md5];
                }
            }
        }
        /// <summary>
        ///     Generates the CSV map.
        /// </summary>
        /// <param name="outputFolder">The output folder.</param>
        /// <externalUnit/>
        /// <revision revisor="dev11" date="2/26/2009" version="1.0.8.0901">
        ///     Member Created
        /// </revision>
        private void GenerateCsvMap(string outputFolder)
        {
            StreamWriter strWriter =
                File.CreateText(Path.Combine(outputFolder, this.csvFilename));

            // a given paper ballot
            PaperBallot ballot;

            // the file name of every page (PDF file name)
            string[] files;

            // write the column headers
            string line = "Ballot,Files";

            strWriter.WriteLine(line);

            // now for each ballot, add a line to the file
            foreach (KeyValuePair <PaperBallot, string[]> pair in
                     this.dicBallots)
            {
                ballot = pair.Key;
                files  = pair.Value;

                line = PaperBallot.GetPdfFilename(ballot);

                foreach (string file in files)
                {
                    line = line + "," + file;
                }

                strWriter.WriteLine(line);
            }

            strWriter.Flush();
            strWriter.Close();
        }