Click here to Skip to main content
15,896,201 members
Articles / Desktop Programming / Windows Forms

Drawing Names (A Christmas Name Drawing Application)

Rate me:
Please Sign up or sign in to vote.
4.78/5 (11 votes)
23 May 2012CPOL17 min read 67.2K   606   26  
A Christmas name drawing application using DHTML, JavaScript, XML, C#, Forms, VS2008, .NET 3.5, encryption.

using System;
using System.IO;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Xml;
using System.Xml.XPath;
using System.Xml.Schema;

namespace NameDrawing
{
    public partial class drawinNames : Form
    {
        public drawinNames()
        {
            InitializeComponent();
        }

        public publicData pd = new publicData();


        //
        //  Draw Names
        //
        public bool doTheNameDraw()
        {
            //
            //  It can be that we get to the "bottom of the hat" and the only name left is yours or your spouses!
            //      So in this case we have to start over
            //  And this may go on and on there is no 100% guarentee that it will halt.
            //
            pd.iOuterRepeats = pd.iInnerRepeats = 0;
            while (1==1)
            {
                pd.iOuterRepeats++;
                if (pd.iOuterRepeats >= 100)
                {
                    return false;
                }
                //
                //  Initialize This Year's Picks To "NOT PICKED"
                //
                for (int iIndex = 1; iIndex < pd.iNumberOfNames + 1; iIndex++)
                {
                    pd.pParticipantList[iIndex].iThisYearsPick = 0;
                    pd.pParticipantList[iIndex].bChosen = false;
                }
                //
                //  Install The Cheats
                //
                for (int iIndex = 0; iIndex < pd.iCheatCount; iIndex++)
                {
                    int iName = pd.cThisYearsCheats[iIndex].iCheatsName;
                    int iThisYearsPick = pd.cThisYearsCheats[iIndex].iCheatsPick;
                    pd.pParticipantList[iName].iThisYearsPick = iThisYearsPick;
                    pd.pParticipantList[iThisYearsPick].bChosen = true;
                }

                //
                //  Draw Names For The Rest
                //
                for (int iIndex = 1; iIndex < pd.iNumberOfNames + 1; iIndex++)
                {
                    //
                    //  If this person already has picked a name then move on
                    //
                    if (pd.pParticipantList[iIndex].iThisYearsPick != 0)
                    {
                        continue;
                    }
                    pd.iInnerRepeats = 0;
                    while (1 == 1)
                    {
                        pd.iInnerRepeats++;
                        if (pd.iInnerRepeats > 100)
                        {
                            break;
                        }
                        //
                        //  Pick A Name Out Of The Hat
                        //
                        int iThisYearsPick = pd.rand.Next(1, pd.iNumberOfNames + 1);
                        //
                        //  You Can Not Pick Yourself
                        //
                        if (iThisYearsPick == iIndex)
                        {
                            continue;
                        }
                        //
                        // You Can Not Pick Someone Who Has Already Been Picked
                        //
                        if (pd.pParticipantList[iThisYearsPick].bChosen == true)
                        {
                            continue;
                        }
                        //
                        //  You Can Not Pick Your Spouse
                        //
                        if (pd.pParticipantList[iIndex].iSpouse == iThisYearsPick)
                        {
                            continue;
                        }
                        //
                        //  You Can Not Pick A Name You Have Drawn Before
                        //
                        bool bNeverPickedThisOneBefore = true;
                        for (int iIndex2 = 0; iIndex2 < pd.iHistoryCount; iIndex2++)
                        {
                            if (pd.hHistoryList[iIndex2].ph[iIndex].iPicked == iThisYearsPick)
                            {
                                bNeverPickedThisOneBefore = false;
                                break;
                            }
                        }
                        if (bNeverPickedThisOneBefore == false)
                        {
                            continue;
                        }
                        //
                        //  Found A Pick
                        //
                        pd.pParticipantList[iIndex].iThisYearsPick = iThisYearsPick;
                        pd.pParticipantList[iThisYearsPick].bChosen = true;
                        break;
                    }
                    if (pd.iInnerRepeats > 100)
                    {
                        break;
                    }
                }
                if (pd.iInnerRepeats > 100)
                {
                    continue;
                }
                break;
            }
            return true;
        }

        //
        //  Choose The Secret Santa And The Target;
        //
        public bool doPickSecretSanta()
        {
            pd.iSanta = pd.iTarget = pd.iSSRedraw = 0;
            while (1==1)
            {
                pd.iSanta = pd.rand.Next(1, pd.iNumberOfNames + 1);
                pd.iTarget = pd.rand.Next(1, pd.iNumberOfNames + 1);
                //
                //  Target & Santa Can Not Be Same Person
                //
                if (pd.iSanta == pd.iTarget)
                {
                    pd.iSSRedraw++;
                    continue;
                }
                //
                //  Target & Santa Can Not Be Spouses
                //
                if (pd.pParticipantList[pd.iSanta].iSpouse == pd.iTarget)
                {
                    pd.iSSRedraw++;
                    continue;
                }
                //
                //  Secret Santa Target Can Not Be The Person Who's Name You Drew
                //
                if (pd.pParticipantList[pd.iSanta].iThisYearsPick == pd.iTarget)
                {
                    pd.iSSRedraw++;
                    continue;
                }
                //
                //  Search The History Validating that the target and santa do not repeat
                //
                bool bFoundARepeat = false;
                for (int iIndex = 0; ((iIndex < pd.iHistoryCount) && (false == bFoundARepeat)); iIndex++)
                {
                    for (int iIndex2 = 0; ((iIndex2 < pd.hHistoryList[iIndex].iParticipantCount) && (false == bFoundARepeat)); iIndex2++)
                    {
                        if ((true == pd.hHistoryList[iIndex].ph[iIndex2].bSanta) &&
                             (pd.hHistoryList[iIndex].ph[iIndex2].iName == pd.iSanta) || (pd.iTarget == pd.hHistoryList[iIndex].ph[iIndex2].iSantaTarget))
                        {
                            bFoundARepeat = true;
                            break;                  // Found A Repeat We Need To Pick Again
                        }
                    }
                    if (bFoundARepeat)
                    {
                        break;  // Found A Repeat We Need To Pick Again
                    }
                }
                if (false == bFoundARepeat)
                {
                    break;  // This Pair Is Unique Done
                }
                pd.iSSRedraw++; // Try Again
            }
            //
            //  Replace '$' with the iSanta.sName and the '*' with the iTarget.sName
            //
            pd.sSecretSantaMsg = pd.sSecretSantaMsg.Replace("$", pd.pParticipantList[pd.iSanta].sName);
            pd.sSecretSantaMsg = pd.sSecretSantaMsg.Replace("*", pd.pParticipantList[pd.iTarget].sName);
            return true;
        }

        //
        //  Draw Names
        //
        private void drawNames_Click(object sender, EventArgs e)
        {
            writeScript.Enabled = true;
            outPutBox.BeginUpdate();
            outPutBox.Items.Clear();
            outPutBox.EndUpdate();

            if ((false == doTheNameDraw()) || (false == doPickSecretSanta()))
            {
                outPutBox.BeginUpdate();
                outPutBox.Items.Add("executeTheDraw FAILED (try again?) ");
                outPutBox.Items.Add("iOuterRepeats = " + pd.iOuterRepeats + " iSSRedraw = " + pd.iSSRedraw);
                outPutBox.EndUpdate();
            }
            else
            {
                if (true == showResults.Checked)
                {
                    outPutBox.BeginUpdate();
                    outPutBox.Items.Add("iOuterRepeats = " + pd.iOuterRepeats + " iSSRedraw = " + pd.iSSRedraw);
                    for (int iIndex = 1; iIndex < pd.iNumberOfNames + 1; iIndex++)
                    {
                        int iThisYearsPick = pd.pParticipantList[iIndex].iThisYearsPick;
                        if (iIndex != pd.iSanta)
                        {
                            outPutBox.Items.Add("Year=:" + pd.sYear + " " + pd.pParticipantList[iIndex].sName + " Picks: " + pd.pParticipantList[iThisYearsPick].sName);
                        }
                        else
                        {
                            outPutBox.Items.Add("Year=:" + pd.sYear + " " + pd.pParticipantList[iIndex].sName + " Picks: " + pd.pParticipantList[iThisYearsPick].sName + " SecretSantaTarget: " + pd.pParticipantList[pd.iTarget].sName);
                        }
                    }
                    outPutBox.EndUpdate();
                }
            }
        }

        //
        //  Load The Data
        //
        private void loadXMLFile_Click(object sender, EventArgs e)
        {
            //
            //  Initialize The Random Number Picker
            //
            pd.rand = new Random();
            
            //
            //  Initialize The Location Of The Data Files
            //
            fbdFindDataFileFolder.Description = "Browse To The Folder That Contains The Data Files";
            fbdFindDataFileFolder.ShowNewFolderButton = false;
            fbdFindDataFileFolder.RootFolder = Environment.SpecialFolder.MyComputer;

            if (fbdFindDataFileFolder.ShowDialog() == DialogResult.OK)
            {
                pd.sDataFolder = fbdFindDataFileFolder.SelectedPath;
            }
            else
            {
                return;
            }

            drawNames.Enabled = true;

            XmlSchemaSet sc = new XmlSchemaSet();
            sc.Add("urn:drawingnames-schema", pd.sDataFolder + "\\drawing_names.xsd");
            XmlReaderSettings settings = new XmlReaderSettings();
            settings.ValidationType = ValidationType.Schema;
            settings.Schemas = sc;
            settings.ProhibitDtd = false;
            settings.ValidationEventHandler += new ValidationEventHandler(ValidationCallBack);
            XmlReader reader = XmlReader.Create(pd.sDataFolder + "\\drawing_names.xml", settings);

            while (reader.Read())
            {
                if (reader.Name.Equals("thisYearsSecretSantaMessage"))
                {
                    pd.sSecretSantaMsg = reader.GetAttribute("sMessage");
                    pd.sYear = reader.GetAttribute("sYear");
                }
                else if (reader.Name.Equals("thisYearsCheatSheet") && (reader.NodeType == XmlNodeType.Element))
                {
                    pd.iCheatCount = Convert.ToInt32(reader.GetAttribute("nCheatCount"));
                    pd.cThisYearsCheats = new cheat[pd.iCheatCount];
                    for (int iIndex = 0; iIndex < pd.iCheatCount; iIndex++)
                    {
                        while (reader.Read())
                        {
                            if (reader.Name.Equals("cheat"))
                            {
                                pd.cThisYearsCheats[iIndex].iCheatsName = Convert.ToInt32(reader.GetAttribute("nCheatsName"));
                                pd.cThisYearsCheats[iIndex].iCheatsPick = Convert.ToInt32(reader.GetAttribute("nCheatNamePicks"));
                                pd.cThisYearsCheats[iIndex].sCheatsDescription = reader.GetAttribute("sDescription");
                                break;
                            }
                        }
                    }
                }
                else if (reader.Name.Equals("historyLog") && (reader.NodeType == XmlNodeType.Element))
                {
                    pd.iHistoryCount = Convert.ToInt32(reader.GetAttribute("nYearCount"));
                    pd.hHistoryList = new history[pd.iHistoryCount];
                    for (int iIndex = 0; iIndex < pd.iHistoryCount; iIndex++)
                    {
                        while (reader.Read())
                        {
                            if (reader.Name.Equals("year") && (reader.NodeType == XmlNodeType.Element))
                            {
                                pd.hHistoryList[iIndex].iYearNumber = Convert.ToInt32(reader.GetAttribute("nYearNumber"));
                                pd.hHistoryList[iIndex].iParticipantCount = Convert.ToInt32(reader.GetAttribute("nameCount"));
                                participantHistory[] phph = new participantHistory[pd.hHistoryList[iIndex].iParticipantCount + 1];
                                pd.hHistoryList[iIndex].ph = phph;
                                for (int iIndexP = 0; iIndexP < pd.hHistoryList[iIndex].iParticipantCount; iIndexP++)
                                {
                                    while (reader.Read())
                                    {
                                        if (reader.Name.Equals("participantHistory"))
                                        {
                                            pd.hHistoryList[iIndex].ph[iIndexP].iName = Convert.ToInt32(reader.GetAttribute("nIndex"));
                                            pd.hHistoryList[iIndex].ph[iIndexP].iPicked = Convert.ToInt32(reader.GetAttribute("nPick"));
                                            pd.hHistoryList[iIndex].ph[iIndexP].bSanta = Convert.ToBoolean(reader.GetAttribute("bSanta"));
                                            if (pd.hHistoryList[iIndex].ph[iIndexP].bSanta)
                                            {
                                                pd.hHistoryList[iIndex].ph[iIndexP].iSantaTarget = Convert.ToInt32(reader.GetAttribute("nSantaTarget"));
                                            }
                                            break;
                                        }
                                    }
                                }
                                break;
                            }
                        }
                    }
                }
                else if (reader.Name.Equals("nameList") && (reader.NodeType == XmlNodeType.Element))
                {
                    pd.iNumberOfNames = Convert.ToInt32(reader.GetAttribute("nListLength"));
                    pd.pParticipantList = new participant[pd.iNumberOfNames + 1];
                    for (int iIndex = 0; iIndex < pd.iNumberOfNames; iIndex++)
                    {
                        while (reader.Read())
                        {
                            if (reader.Name.Equals("participantData"))
                            {
                                int iLocation = Convert.ToInt32(reader.GetAttribute("nIndex"));
                                pd.pParticipantList[iLocation].iSpouse = Convert.ToInt32(reader.GetAttribute("sSpouse"));
                                pd.pParticipantList[iLocation].sName = reader.GetAttribute("sName");
                                pd.pParticipantList[iLocation].sPassPhrase = reader.GetAttribute("sPassPhrase");
                                pd.pParticipantList[iLocation].sDrawMessage = reader.GetAttribute("sDrawMessage");
                                pd.pParticipantList[iLocation].sSantaMessage = reader.GetAttribute("sMessageSanta");
                                break;
                            }
                        }
                    }
                }
            }

            reader.Close();

            //
            //  Display The Data If User Indicates To Do So
            //
            if (true == showResults.Checked)
            {
                displayXMLContent();
            }
        }

        //
        //  In Case The XML File Violates The XSD Schema
        //
        public void ValidationCallBack(object sender, ValidationEventArgs args)
        {
            pd.isValid = false;
            outPutBox.BeginUpdate();
            outPutBox.Items.Add("Validation event\n" + args.Message);
            outPutBox.EndUpdate();
        }

        //
        //  Display Input Data
        //
        public void displayXMLContent()
        {
            outPutBox.BeginUpdate();
            outPutBox.Items.Add("sSecretSantaMsg ..... " + pd.sSecretSantaMsg);
            outPutBox.Items.Add("iCheatCount ......... " + pd.iCheatCount);
            for (int iIndex = 0; iIndex < pd.iCheatCount; iIndex++)
            {
                outPutBox.Items.Add("iCheatsName ......... " + pd.cThisYearsCheats[iIndex].iCheatsName);
                outPutBox.Items.Add("iCheatsPick ......... " + pd.cThisYearsCheats[iIndex].iCheatsPick);
                outPutBox.Items.Add("sCheatsDescription .. " + pd.cThisYearsCheats[iIndex].sCheatsDescription);
            }
            outPutBox.Items.Add("iHistoryCount ...... " + pd.iHistoryCount);
            for (int iIndex = 0; iIndex < pd.iHistoryCount; iIndex++)
            {
                outPutBox.Items.Add("iYearNumber ......... " + pd.hHistoryList[iIndex].iYearNumber);
                for (int iIndex2 = 1; iIndex2 <= pd.hHistoryList[iIndex].iParticipantCount; iIndex2++)
                {
                    outPutBox.Items.Add("iName ............... " + pd.hHistoryList[iIndex].ph[iIndex2].iName);
                    outPutBox.Items.Add("iPicked ............. " + pd.hHistoryList[iIndex].ph[iIndex2].iPicked);
                    outPutBox.Items.Add("bSanta .............. " + pd.hHistoryList[iIndex].ph[iIndex2].bSanta);
                    outPutBox.Items.Add("iSantaTarget ........ " + pd.hHistoryList[iIndex].ph[iIndex2].iSantaTarget);
                }
            }
            outPutBox.Items.Add("iNumberOfNames ..... " + pd.iNumberOfNames);
            for (int iIndex = 0; iIndex < pd.iNumberOfNames; iIndex++)
            {
                outPutBox.Items.Add("sName ............... " + pd.pParticipantList[iIndex].sName);
                outPutBox.Items.Add("iSpouse ............. " + pd.pParticipantList[iIndex].iSpouse);
                outPutBox.Items.Add("sPassPhrase ......... " + pd.pParticipantList[iIndex].sPassPhrase);
                outPutBox.Items.Add("sDrawMessage ........ " + pd.pParticipantList[iIndex].sDrawMessage);
                outPutBox.Items.Add("sSantaMessage ....... " + pd.pParticipantList[iIndex].sSantaMessage);
            }
            outPutBox.EndUpdate();
        }

        //
        //  A Test Of The Crypt Function
        //
        private void bCrypt_Click(object sender, EventArgs e)
        {
            tbCryptText.Text = Crypt(tbClearText.Text, tbPassPhrase.Text);
        }

        //
        //  Return An Encrypted Version Of sClearText Using sPassPhrase.
        //
        public string Crypt(string sClearText, string sPassPhrase)
        {
            Char[] cMyAlphabet = new Char[] { '$', 'A', 'a', '1', 'B', 'b', '2', 'C', 'c', '3', 'D', 'd', '4', 'E', 'e', '5', 'F', 'f', '6', 'G', 'g', '7', 'H', 'h', '8', 'I', 'i', '9', 'J', 'j', '0', 'K', 'k', ' ', 'L', 'l', 'M', 'm', 'N', 'n', 'O', 'o', 'P', 'p', 'Q', 'q', 'R', 'r', 'S', 's', 'T', 't', 'U', 'u', 'V', 'v', 'W', 'w', 'X', 'x', 'Y', 'y', 'Z', 'z' };
            string sMyAlphabet;
            string sCryptText = "";
            sMyAlphabet = "$Aa1Bb2Cc3Dd4Ee5Ff6Gg7Hh8Ii9Jj0Kk LlMmNnOoPpQqRrSsTtUuVvWwXxYyZz";

            char[] cCryptText = new char[sClearText.Length];
            
            char[] cClearText = new char[sClearText.Length];
            cClearText = sClearText.ToCharArray();

            char[] cPassPhrase = new char[sPassPhrase.Length];
            cPassPhrase = sPassPhrase.ToCharArray();

            //
            //  Patch Up The Pass Phrase If Necessary
            //
            int iIllegalCharacterIndex = 1; // Use This Location In myAlphebet To Replace Illegal Characters In The Pass Phrase
            for (int iIndex = 0; iIndex < sPassPhrase.Length; iIndex++)
            {
                if (false == sMyAlphabet.Contains(cPassPhrase[iIndex]))
                {
                    cPassPhrase[iIndex] = cMyAlphabet[iIllegalCharacterIndex];
                    iIllegalCharacterIndex++;
                    if (iIllegalCharacterIndex > sMyAlphabet.Length)
                    {
                        iIllegalCharacterIndex = 1;
                    }
                }
            }

            //
            //  Create The Encrypted Version Of The Clear Text Message
            //
            int iLocInAlphabet;
            int iLocInPassPhrase;
            int iLocCryptCharacter;
            for (int iIndex = 0; iIndex < sClearText.Length; iIndex++)
            {
                // find the location in the alphabet of (this) character in the clear text message
                iLocInAlphabet = sMyAlphabet.IndexOf(cClearText[iIndex]);

                // find the location in the alphabet of (this) character in the pass pharse (modulo the lenght of the pass phrase which could be shorter than the clear text message)
                iLocInPassPhrase = sMyAlphabet.IndexOf(cPassPhrase[iIndex % sPassPhrase.Length]);

                // XOR the two values together (modulo the length of the alphebet)
                iLocCryptCharacter = (iLocInAlphabet ^ iLocInPassPhrase) % sMyAlphabet.Length;

                // The resulting value is the encrypted value.
                cCryptText[iIndex] = cMyAlphabet[iLocCryptCharacter];
            }

            //
            // Convert Encrypted Character Array To A String
            //
            for (int iIndex = 0; iIndex < sClearText.Length; iIndex++)
            {
                sCryptText = sCryptText + cCryptText[iIndex].ToString();
            }
            return sCryptText;
        }

        //
        //  Create The Crypt.js Java Script
        //
        public void writeScript_Click(object sender, EventArgs e)
        {
            bViewPage.Enabled = true;
            //
            //  Encrypt The Secret Santa Message
            //
            pd.sCryptSecretSantaMsg = Crypt(pd.sSecretSantaMsg, pd.pParticipantList[pd.iSanta].sPassPhrase);
            //
            //  Create The Encrypted Version Of The Announcement Messages For Each participant
            //
            for (int iIndex = 1; iIndex < pd.iNumberOfNames+1; iIndex++)
            {
                pd.pParticipantList[iIndex].sCryptPick = Crypt(pd.pParticipantList[pd.pParticipantList[iIndex].iThisYearsPick].sDrawMessage, pd.pParticipantList[iIndex].sPassPhrase);
                if (iIndex == pd.iSanta)
                {
                    pd.pParticipantList[iIndex].sCryptSSPick = pd.sCryptSecretSantaMsg;
                }
                else
                {
                    pd.pParticipantList[iIndex].sCryptSSPick = Crypt(pd.pParticipantList[iIndex].sSantaMessage, pd.pParticipantList[iIndex].sPassPhrase);
                }
            }

            //
            //  Write Top Part Of The Script.
            //
            StreamWriter fCryptJsLines = new StreamWriter(pd.sDataFolder + "\\crypt.js", false);
            StreamReader fCryptJsTop = new StreamReader(pd.sDataFolder+"\\crypt_top.js");
            string sCryptJsTopLine;
            while(null != (sCryptJsTopLine = fCryptJsTop.ReadLine()))
            {
                fCryptJsLines.WriteLine(sCryptJsTopLine);
            }
            fCryptJsTop.Close();

            //
            //  Write The Middle Part Of The Script
            //
            for (int iIndex = 1; iIndex < pd.iNumberOfNames; iIndex++)
            {
                fCryptJsLines.WriteLine("        '" + pd.pParticipantList[iIndex].sCryptPick + "',");
                fCryptJsLines.WriteLine("        '" + pd.pParticipantList[iIndex].sCryptSSPick + "',");
            }
            fCryptJsLines.WriteLine("        '" + pd.pParticipantList[pd.iNumberOfNames].sCryptPick + "',");
            fCryptJsLines.WriteLine("        '" + pd.pParticipantList[pd.iNumberOfNames].sCryptSSPick + "'");

            //
            //  Write The Bottom Part Of The Script
            //
            StreamReader fCryptJsBottom = new StreamReader(pd.sDataFolder+"\\crypt_bottom.js");
            string sCryptJsBottomLine;
            while (null != (sCryptJsBottomLine = fCryptJsBottom.ReadLine()))
            {
                fCryptJsLines.WriteLine(sCryptJsBottomLine);
            }
            fCryptJsBottom.Close();
            fCryptJsLines.Close();
            return;
        }

        //
        //  Bring Up The Page That Uses The Crypt.JS
        //
        private void bViewPage_Click(object sender, EventArgs e)
        {
            string sPage = pd.sDataFolder + "\\index.html";
            wbWindow.Navigate( new Uri(sPage));
        }
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
-- N/A --
United States United States
My educational background is Mathematics, Physics and Computer Science. I also earned a secondary teaching certificate.

My professional background is as a Software Engineer for the past 25 years or so and before that an instructor of Mathematics and Computer Science at the college level.

I currently design, develop, and support standards based Application Programming Interfaces that allow Windows based applications to interact with financial devices in a vendor neutral manner.

My hobbies are cycling, playing with the Internet, and reading.

Comments and Discussions