/// <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];
                }
            }
        }
示例#2
0
        /// <summary>
        ///     Extracts the cards and faces from the ballot and creates
        ///     duplicates that are added to the corresponding collections, plus
        ///     adding a duplicate of the ballot to the collection. Notice that
        ///     cards and ballot duplicates have the inner collections empty, so
        ///     that the serialization do not create those collections as part
        ///     of the resulting XML.
        /// </summary>
        /// <param name="ballot">The ballot.</param>
        /// <externalUnit cref="Ballot"/>
        /// <externalUnit cref="Card"/>
        /// <externalUnit cref="CardList"/>
        /// <externalUnit cref="Face"/>
        /// <externalUnit cref="FaceList"/>
        /// <revision revisor="dev11" date="12/16/2008" version="1.0.0.0">
        ///     Member Created
        /// </revision>
        /// <revision revisor="dev11" date="02/20/2009" version="1.0.8.0301">
        ///     Added face reuse and removal of duplicates
        /// </revision>
        /// <revision revisor="dev11" date="03/04/2009" version="1.0.8.1501">
        ///     since a ballot style can be used for multiple precincts, and the
        ///     precinct id is now part of the barcode, the ballot style id is
        ///     no longer enough to uniquely identify a ballot on the
        ///     Ballots.xml file. So now, the id is a sequential number.
        /// </revision>
        /// <revision revisor="dev11" date="03/06/2009" version="1.0.8.1701">
        ///     added support for new ballot attributes (ballot style id and
        ///     precinct id).
        /// </revision>
        /// <revision revisor="dev11" date="03/16/2009" version="1.0.8.2701">
        ///     changed local variables name
        /// </revision>
        public void AddBallot(Ballot ballot)
        {
            // create a dictionary of faces to keep track of unique faces
            // each key represents an MD5 hash of the collection of marks of
            // a face. Any two faces with identical collection of marks are
            // considered the same even if their face ids are different. In that
            // case, discard the newer one, and reuse the old one as saved on
            // the dictionary
            string md5;
            Face   uniqueFace;

            // create a duplicate of the ballot so that the cards collection is
            // populated with custom duplicates
            Ballot ballotToCard = new Ballot();

            // make it 1-based identifier
            ballotToCard.Id            = 1 + this.ballots.Count;
            ballotToCard.BallotStyleId = ballot.BallotStyleId;
            ballotToCard.PrecinctId    = ballot.PrecinctId;
            ballotToCard.Cards         = new CardList();

            // add the ballot duplicate to the ballots collection
            this.ballots.Add(ballotToCard);

            foreach (Card card in ballot.Cards)
            {
                // create a duplicate of the card so that the faces collection
                // is populated with custom duplicates
                Card cardToFace = new Card();
                cardToFace.Barcode = card.Barcode;
                cardToFace.Id      = card.Id;
                cardToFace.Faces   = new FaceList();

                // Add the duplicate card to the cards collection.
                // This duplicate links a card to a face.
                this.cards.Add(cardToFace);
                foreach (Face face in card.Faces)
                {
                    // get the MD5 hash of the collection of marks of the
                    // current face
                    md5 = BitConverter.ToString(ObjectMD5.Generate(face.Marks));

                    // check if an identical collection is already in use
                    if (this.faceMap.ContainsKey(md5) == true)
                    {
                        // a face with an identical collection of marks is
                        // already in use so get it from the dictionary
                        uniqueFace = this.faceMap[md5];
                    }
                    else
                    {
                        // no existing face up to this point has the same
                        // collection of marks, so add the face to the
                        // dictionary using the MD5 hash
                        this.faceMap.Add(md5, face);

                        // add the new face since all marks need to be included
                        // as well on the [Faces.xml] file
                        this.faces.Add(face);

                        // use this face as the [uniqueFace]
                        uniqueFace = face;
                    }

                    // create the face entry that goes on the current card
                    // This is the face instance that appears on the [Cards.xml]
                    // file and doesn't contain any marks in it. It is simply
                    // a pointer to the corresponding face entry on the
                    // [Faces.xml]where all marks are defined
                    Face faceToMark = new Face();

                    // map to the uniqueFace using the [id]
                    faceToMark.Id = uniqueFace.Id;

                    // add the duplicate of the face to the current card
                    // collection that generates the [Cards.xml] file
                    // this duplicate do not contain the marks
                    cardToFace.Faces.Add(faceToMark);
                }

                // create another card duplicate to link the ballot to the card
                // and add it to the collection of cards of the ballot duplicate
                Card cardFromBallot = new Card();
                cardFromBallot.Barcode = card.Barcode;
                cardFromBallot.Id      = card.Id;
                ballotToCard.Cards.Add(cardFromBallot);
            }
        }