Register
It is currently Thu Jul 24, 2014 8:37 am

secretsanta bash script


All times are UTC - 6 hours


Post new topic Reply to topic  [ 8 posts ] 
Author Message
 PostPosted: Fri Jan 22, 2010 5:54 am   
User avatar

Joined: Mon Jan 18, 2010 8:10 pm
Posts: 40
Hello BashScripts.org,

My name is Free. I have a bash script that I would like to share with you.

I have been been using linux operating systems for about two years. Last summer, I bought the bash programming book, Learning the bash Shell by Newham and Rosenblatt. My first bash program was for renaming files. When I finished it, I was dying to try something else.

I got the inspiration for the next project from a family Christmas tradition. In my family, we do Secret Santa gift-exchanges--where everyone draws a name from a hat, gives a gift anonymously to one person, and gets a gift in return from another anonymous person, his or her "Secret Santa". The trouble we have is getting together to draw names from a hat or finding an alternative way to randomly and "non-transparently" assign names. For years I imagined writing a computer program that could do the name drawing, and this year I finally had a chance to realize it.

Anyway, I wrote a quick and dirty version from the family gift exchange this Christmas, and it was a(n) (almost) complete success. It got the names drawn so that I could send them off without looking at them. It checked that no one picked their own name and that everyone's name was picked by someone. Everyone was happy with it, but it was quickly suggested that the program be expanded to include a check for disallowed draws (e.g. husband and wife cannot draw each other's name). Since Christmas, I have added the exclusion feature and expanded the mechanism for automatically verifying that no errors occurred in the draw. Also I have added copious comments and generally tried to clean it up and make it pretty.

It was a real challenge and I learned a lot from it. I want to pass it on to you, because I would like to know what someone else thinks of it. I hope you like it. Please let me know what you think...


Top
 Profile  
 PostPosted: Fri Jan 22, 2010 6:03 am   
User avatar

Joined: Mon Jan 18, 2010 8:10 pm
Posts: 40
Code:
#!/bin/bash
#
#  SecretSanta:
#
#  A program to simulate drawing names from a hat for a gift exchange
#
#    This program will ask for a list of names. It will then randomly
#  draw a name for each person--checking that the person did not
#  draw his or her own name or the name of a person to be disallowed.
#    When the program draws a legal name for a person, a text file
#  with that person's name on it will be created to identify who they
#  have picked. By default the person running the program does not
#  see what names are picked for each person. He or she can then send
#  the output files to the people on the list, without knowing who
#  they picked.
#    The program includes an option to check that all the output files
#  have legal picks and that all names on the list have been picked.
#
#  By: Geoffrey Warne
#  Email: geoffreywarne@gmail.com
#  Last Edit: January 25, 2010

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#  getoptions: The first function to run, 'get_options' looks for
#  valid options given by the operator on the command line. A 'help'
#  option is included to list the available options.
function get_options
{
            # Check positional parameters for
            # options
optlist=$@         
            # Set default option values
secret="yes"         
disallow="no"
verbose="no"
remove="no"
pickcheck="no"
help="no"
keep="no"
useold="no"

            # Check for each option and set values
for opt in $optlist; do      
   option=$opt
   if [ $option = "-ns" ]; then secret="no"; fi
   if [ $option = "-x" ]; then disallow="yes"; fi
   if [ $option = "-v" ]; then verbose="yes"; fi
   if [ $option = "-rm" ]; then remove="yes"; fi
   if [ $option = "-chk" ]; then pickcheck="yes"; fi
   if [ $option = "-h" ]; then help="yes"; fi
   if [ $option = "-k" ]; then keep="yes"; fi
   if [ $option = "-o" ]; then useold="yes"; fi
done
            # Print 'help' menu if requested
if [ $help = "yes" ]; then   
   echo "Usage: secretsanta [Option] [Option] [...]"
   echo "Options:   -ns : not secret (view picks)"
   echo "      -x  : disallow picks"
   echo "      -v  : verbose output"
   echo "      -rm : remove existing files"
   echo "      -chk: include pickcheck"
   echo "      -h  : help"
   echo "      -k  : keep list after completion"
   echo "      -o  : use old (existing) list"
   echo
   echo "Note: To have output printed to a file,"
   echo "please try: secretsanta [Option] [Option] [...] | tee [Filename]"
   echo
   exit 0
fi
            # If 'verbose' option is given,
            # Print out list of options and values
if [ $verbose = "yes" ]; then
   echo "Options ($#): $optlist"
   echo
   echo "Secret? $secret"
   echo "Disallow? $disallow"
   echo "Verbose? $verbose"
   echo "Remove? $remove"
   echo "Pickcheck? $pickcheck"
   echo "Keep? $keep"
   echo "Useold? $useold"
   echo
fi
            # If 'useold' option is given,
            # Check for existing list to use;
            # Otherwise get a new list
if [ $useold = "yes" ] && [ ! -s SantaList.txt ]; then
   echo "There is no existing list. Getting new list..."
   echo
   useold="no"
fi
}

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#  setup: This function removes existing files from previous runs
#  and prepares fresh files. Removal and output will depend on options
#  given (especially -rm, -o, and -v) and which files currently exist.
function setup
{
echo "Setup"
echo "~~~~~"
            # Starting with SantaList,
            # If file does not exist,
            # Then create it
if [ ! -e ./SantaList.txt ]; then
   if [ $verbose = "yes" ]; then echo "Creating new file, SantaList.txt..."; echo; fi
   touch ./SantaList.txt
            # If 'useold' option is on,
            # Use existing list
else
   if [ $useold = "yes" ]; then
      if [ $verbose = "yes" ]; then echo "Use old option (-o) set... Using existing list..."; echo; fi
            # Otherwise, delete existing list,
            # and create a new one
   else
      if [ $verbose = "yes" ]; then echo "Removing previous list..."; fi
      rm ./SantaList.txt
      if [ $verbose = "yes" ]; then echo "Creating new list..."; echo; fi
      touch ./SantaList.txt
   fi
fi
            # Next, set output file directory...
            # If directory does not yet exist,
            # Create it;
if [ ! -e ./SecretSanta ]; then
   if [ $verbose = "yes" ]; then echo "Making new directory, SecretSanta, in current directory..."; fi
   mkdir ./SecretSanta
            # Otherwise, delete existing files
else
   if [ $verbose = "yes" ]; then echo "Directory, SecretSanta, already exists."; fi
   if [ ! -z "$(ls ./SecretSanta)" ]; then
            # If "remove" option is active,
            # Automatically delete output files
      if [ $verbose = "yes" ]; then echo "Directory not empty."; fi
      if [ $remove = "yes" ]; then
         if [ $verbose = "yes" ]; then echo "Remove option? Yes... Removing files..."; fi
         rm -R ./SecretSanta/*
            # Otherwise, give operator a chance to
            # to review files and keep if desired
      else
         if [ $verbose = "yes" ]; then echo "Remove option? No"; fi
         echo "Remove existing Secret Santa files?"
         echo "(New files with same names will be overwritten)"
         rm -R -i ./SecretSanta/*
      fi
            # If directory is empty, do nothing
   else
      if [ $verbose = "yes" ]; then echo "Directory is empty."; fi
   fi
fi
}


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#  get_list: This function gets a list of names for the secret santa
#  pool. Once it knows how many people are in the pool, it calls on the
#  function, get_name, to get the names. If the 'disallow' option is
#  active, this function will call on the function, disallow, to get
#  disallowed names. If the 'useold' option is active, secretsanta will
#  will use an existing list.
function get_list
{
            # First time around $1 should be zero
LOOP=$1
            # Check if 'useold' option is on
if [ $useold = "no" ]; then
            # Only print header first time around
   if [ $LOOP = 0 ]; then echo; echo "Get List"; echo "~~~~~~~~"; fi
            # Prompt operator for size of pool
            # Returning an empty value will yield
            # a pool size of zero
   echo -n "How many people in list? "; read NUMBER
   NUMBER=${NUMBER:=0}
            # If operator enters a non-number,
            # Or a number less than 3,
            # Loop back to top of function,
            # Setting $1 to 1 (indicating a loop)
   if !(echo $NUMBER | grep -q "^[0-9]*$"); then get_list 1; return; fi   
   if [ $NUMBER -lt 3 ]; then echo "Number must be greater than two."; get_list 1; return; fi
   echo
            # For number of people in the pool,
            # Run function, get_name, and
            # Append name to list of people
   for (( ORDER=1; ORDER <= $NUMBER; ORDER++)); do
      get_name $ORDER
      echo -n "$NAME:" >> ./SantaList.txt
            # If 'disallow' option is on,
            # Run function, disallow, to get
            # the name of one disallowed draw
      if [ $disallow = "yes" ]; then disallow $NAME; fi
      echo $DISALLOWED >> ./SantaList.txt
   done
else            # If "useold" option is on,
            # Do not touch existing SantaList,
            # And count existing number of lines
   let -i NUMBER=$(cat ./SantaList.txt | wc -l)
fi
}

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#  get_name: This is part of the parent function, get_list. It prompts
#  the operator for each name in the pool list and checks that it is
#  valid.
function get_name
{
            # Parent function, get_list, sends the
            # Line number of the name to get, here
   ORDER=$1
            # Prompt operator for a name
   echo -n "Please enter name #$ORDER: "
   read NAME
            # Check validity of name entered:
            # Not empty, "NONE", or a name already
            # given
   if [ "$NAME" = "" ]; then echo "Name must have at least one character..."; get_name $ORDER; return; fi
   if [ "$NAME" = "NONE" ]; then echo "NONE is a reserved word..."; get_name $ORDER; return; fi
            # Check for two or more words
   if (echo "$NAME" | grep -q " "); then echo "Only one name (no spaces)..."; get_name $ORDER; return; fi
   if (cat ./SantaList.txt | cut -d: -f1 | grep -q -x "$NAME"); then echo "Name, $NAME, is already listed"; get_name $ORDER; return; fi
}

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#  disallow: This is part of the function, get_list. When 'disallow'
#  option is active, this function asks the operator for a name that
#  current person in list is not allowed to draw.
function disallow
{
            # Prompt user for disallowed name
echo -n "Enter disallowed name for $1: "
read DISALLOWED
if (echo "$DISALLOWED" | grep -q " "); then echo "Only one name (no spaces)..."; disallow $NAME; return; fi
            # If no disallowed name is given,
            # Set exclusion to default, "NONE"
DISALLOWED=${DISALLOWED:="NONE"}
}

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#  take_turns: This function is called in the body of 'secretsanta'.
#  Here, a name is drawn ($PICK) for each of the people ($SANTA) in the
#  pool. If a person draws their own name or a disallowed name, the
#  child function, draw, will loop until a valid pick is made. When
#  all Santas have drawn names, the names with be written to output
#  files ($SANTA.txt).
#    If the draw cannot complete (because either the last person's own
#  name or a disallowed name are the only names left at the end of the
#  round), this function will loop as a new round. If five rounds are
#  completed unsuccessfully, the program will exit.
function take_turns
{
            # Parent function, secretsanta, and
            # loop send number of people and round
            # number, here
NUMBER=$1
ROUND=$2
            # At the start of the first round,
            # Print the function heading
if [ $ROUND -eq 1 ]; then
   echo
   echo "Drawing"
   echo "~~~~~~~"
fi   

            # If five rounds have completed
            # unsuccessfully, print message and
            # exit.
if [ $ROUND -eq 6 ]; then echo "Too many rounds... Cannot complete... Please redo list."; exit 1; fi
            # Print the round number
echo "Round: $ROUND"
            # Clean up any temporary files left
            # from previous runs
if [ -e /var/tmp/Draws.txt ]; then rm /var/tmp/Draws.txt; fi
touch /var/tmp/Draws.txt
if [ -e /var/tmp/DrawsRandom.txt ]; then rm /var/tmp/DrawsRandom.txt; fi
touch /var/tmp/DrawsRandom.txt
            # Cut out names from the pool list and
            # place them in a "hat"
cat ./SantaList.txt | cut -d: -f1 >> /var/tmp/SantaHat

            # Start TURN count at zero
let -i TURN=0
            # Read pool list, 'SantaList.txt'
            # for Santa and disallowed names
            # Then send names, line-by-line to
            # child function, draw
for LINE in $(cat ./SantaList.txt); do
   SANTA=$(echo $LINE | cut -d: -f1)
   if [ $disallow = "yes" ]; then DISALLOWED=$(echo $LINE | cut -d: -f2); fi
   DISALLOWED=${DISALLOWED:="NONE"}
            # Each person, one-by-one, takes a turn
   let TURN=TURN+1
   echo -n "$TURN) $SANTA --> "
   draw $TURN $NUMBER $SANTA $DISALLOWED
            # Check if round ended successfully,
            # If not, then go on to next round
   if [ $? = "2" ]; then let ROUND=ROUND+1; take_turns $NUMBER $ROUND; return; fi
            # If 'secret' option is turned off,
            # print out the name that was drawn
   if [ $secret = "no" ]; then echo -n "$PICK --> "; else echo -n "--> "; fi
            # Print name of output file
   echo "$SANTA.txt"   
            # Record name picked in temporary file
   echo $PICK >> /var/tmp/Draws.txt
            # Create output file with the name of
            # the person who is drawing on it
   echo "Your name: $SANTA" > ./SecretSanta/"$SANTA.txt"
   echo "Your pick: $PICK" >> ./SecretSanta/"$SANTA.txt"
            # Remove the name that was drawn from
            # the hat
   sed '1d' /var/tmp/SantaHatRandom > /var/tmp/SantaHat
done
}

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#  draw: Child to function, take_turns, this function random sorts
#  the (remaining) names in the hat (SantaHat) and draws the first
#  name off the top of the list. It then checks is the draw is valid
#  and loops back if the draw is not valid.
function draw
{

            # Parent function and loop send
            # variables here
TURN=$1
NUMBER=$2
SANTA=$3
DISALLOWED=$4
DISALLOWED=${DISALLOWED:="NONE"}
            # Random sort the names in the hat file
            # and pick the first one off the top
sort -R /var/tmp/SantaHat > /var/tmp/SantaHatRandom
read PICK < /var/tmp/SantaHatRandom
            # If there are only two names left, the
            # name of the person who is drawing and
            # his or her disallowed name, then end
            # round
if [ $(cat /var/tmp/SantaHat | wc -l) = 2 ] && (cat /var/tmp/SantaHat | grep -q $SANTA) && (cat /var/tmp/SantaHat | grep -q $DISALLOWED); then echo "Only Two Names Left (Santa and Disallowed)... Start Over"; echo; rm /var/tmp/SantaHat; return 2; fi
            # If the last person draws their own
            # name or their disallowed name, then
            # end round
if [ $TURN = $NUMBER ] && [ $PICK = $SANTA ]; then echo "Santa left with own name... Start Over"; echo; rm /var/tmp/SantaHat; return 2; fi
if [ $TURN = $NUMBER ] && [ $PICK = $DISALLOWED ]; then echo "Santa left with disallowed name... Start Over"; echo; rm /var/tmp/SantaHat; return 2; fi
            # If 'verbose', echo picked name
if [ $PICK = $SANTA ] && [ $verbose = "yes" ]; then echo -n "$PICK, "; fi
if [ $PICK = $DISALLOWED ] && [ $verbose = "yes" ]; then echo -n "$PICK, "; fi
            # If person draws own name or
            # disallowed name, then draw again
if [ $PICK = $SANTA ]; then draw $TURN $NUMBER $SANTA $DISALLOWED; fi
if [ $PICK = $DISALLOWED ]; then draw $TURN $NUMBER $SANTA $DISALLOWED; fi
}

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#  pickcheck: If the 'pickcheck' option (-chk) is on, check if the
#  output files are correct. Check that everyone on the list got a file
#  with their name on it. Check that they got a pick and that it is not
#  themselves or a disallowed name. Finally, check that all the names
#  on the list were picked.
function pickcheck
{
let -i ERRORS=0
# Print formatted chart headings
echo "Pick Check"
echo "~~~~~~~~~~"
printf "%-12s" "Santa"
printf "%-12s" "Disallow"
printf "%-12s" "Card File"
printf "%-12s" "Card Name"
printf "%-12s" "Pick"
printf "%-12s" "Self"
printf "%-12s" "Disallowed"
printf "%-12s\n" "Picked Once"
printf "%-12s" "~~~~~"
printf "%-12s" "~~~~~~~~"
printf "%-12s" "~~~~~~~~~"
printf "%-12s" "~~~~~~~~~"
printf "%-12s" "~~~~"
printf "%-12s" "~~~~"
printf "%-12s" "~~~~~~~~~~"
printf "%-12s\n" "~~~~~~~~~~~"

# Read the pool list (SantaList.txt) line-by-line,
# And get the name of person to check (SANTA) and
# a disallowed name (DISALLOWED). If there is no disallowed name,
# set it to "NONE", as the default.
# Also, get all other relevent values for validating draws, and
# set appropriate defaults.
for LINE in $(cat ./SantaList.txt); do
   SANTA=$(echo $LINE | cut -d: -f1)
   if (ls ./SecretSanta/ | grep -q -x "$SANTA.txt"); then
      SANTACARD="$SANTA.txt"
   else SANTACARD="NONE"
   fi

   #Get all relevent values from output files
   #(./SecretSanta/$SANTA.txt)
   if [ ! $SANTACARD = "NONE" ]; then
      PICKLINE=$(cat ./SecretSanta/$SANTA.txt | grep "Your pick: ")
      PICK=${PICKLINE#Your pick: *}
      PICK=${PICK:="NONE"}
      NAMELINE=$(cat ./SecretSanta/$SANTA.txt | grep "Your name: ")
      YOUR_NAME=${NAMELINE#Your name: *}
      YOUR_NAME=${YOUR_NAME:="NONE"}
   else
      PICK="---"
      YOUR_NAME="---"
   fi
   if [ $disallow = "yes" ]; then
      DISALLOWED=$(echo $LINE | cut -d: -f2)
      DISALLOWED=${DISALLOWED:="NONE"}
   else
      DISALLOWED="NONE"
   fi
   #Count and list SecretSanta(s) for each name in list
   let -i SS=0
   for FILE in $(ls ./SecretSanta/); do
      if (cat ./SecretSanta/$FILE | grep -q -x "Your pick: $SANTA"); then
         let SS=SS+1
         SECRETSANTA[$SS]=$FILE
      fi
   done
   #Print out verbose header
   if [ $verbose = "yes" ]; then
      echo
      printf "%-24.23s" "$LINE"
      printf "%-12.11s" "$SANTACARD"
      printf "%-12.11s" "$YOUR_NAME"
      if [ $secret = "no" ] || [ $PICK = "NONE" ] || [ $PICK = "---" ]; then printf "%-12.11s" "$PICK"; else printf "%-12s" "Secret"; fi
      printf "%-12.11s" "($SANTA)"
      printf "%-12.11s" "($DISALLOWED)"
      if [ $secret = "no" ]; then
         for (( i=1 ; i <= $SS ; i++ )); do
            echo -n "${SECRETSANTA[$i]},"
         done
         if [ $SS -eq 0 ]; then echo -n "NONE"; fi
         echo
      else
         echo "SS=$SS"
      fi
   fi

   printf "%-12.11s" $SANTA
   printf "%-12.11s" $DISALLOWED

   #Check for file with each person's name on it ($SANTA.txt).
   if [ $SANTACARD = "NONE" ]; then
      let ERRORS=ERRORS+1
      printf "%-12s" "NO [$ERRORS]"
      no_file="yes"
   else
      printf "%-12s" "yes"
      no_file="no"
   fi

   #If there is a file with the person's name on it,
   #Check to see if the name inside is the same
   if [ $no_file = "no" ]; then
      if [ $SANTA = $YOUR_NAME ]; then
         printf "%-12s" "yes"

      else
         let ERRORS=ERRORS+1
         printf "%-12s" "NO [$ERRORS]"
      fi
   else
      printf "%-12s" "---"
   fi

   #If there is a file with the person's name on it,
   #Check if their pick was good
   if [ $no_file = "no" ]; then
      #Check that each person has a name that is in the list
      if !((cat SantaList.txt | cut -d: -f1) | grep -q -x $PICK); then
         let ERRORS=ERRORS+1
         printf "%-12s" "NO [$ERRORS]"
      else
         printf "%-12s" "yes"
      fi      

      
      #If there is a pick to check, check whether it is legal   
      if [ $PICK = "NONE" ]; then
         printf "%-12s" "---"
         printf "%-12s" "---"
      else
         #Check if the person picked their own name
         if [ $PICK = $SANTA ]; then
            let ERRORS=ERRORS+1
            printf "%-12s" "YES [$ERRORS]"
         else
            printf "%-12s" "no"
         fi      

         #Check if the person picked their disallowed name
         if [ $PICK = $DISALLOWED ]; then
            let ERRORS=ERRORS+1
            printf "%-12s" "YES [$ERRORS]"
         else
            printf "%-12s" "no"
         fi
      fi
   #If there is no file with the person's name on it,
   #Cannot check the pick, so print "---" and move on
   else
      printf "%-12s" "---"
      printf "%-12s" "---"
      printf "%-12s" "---"
   fi

   #Check all output files ($CHECK.txt),
   #To make sure that all names have been picked.
   if [ $SS -eq 1 ]; then
      printf "%-12s\n" "yes"
   else
      let ERRORS=ERRORS+1
      printf "%-12s\n" "NO [$ERRORS]"
   fi
done
echo
#Print error count
echo "[Errors: $ERRORS]"; echo
}

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#  BODY:
#  This is the main body of the program. It runs the child functions,
#  get_options, cleanup, get_list, take_turns, and (if the 'pickcheck'
#  option is set) pickcheck. Here the title, the pool list, a list of
#  disallowed names, a list of picked names (random), and the list of
#  output files are displayed. Temporary files are removed. If the
#  'keep' function is on, the pool list is not deleted.
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

            # Print title
echo "          _______           "
echo "       __/       \          "
echo "      /           \         "
echo "   __/             \_       "
echo "  /             \_   \_***  "
echo " /                \___/   * "
echo " ~~~~~~~~~~~~~~~~~~   *   * "
echo "{   Secret Santa   }   ***  "
echo " ~~~~~~~~~~~~~~~~~~         "
echo
            # Run function to get a list of options
get_options $@
            # Run function to remove old files and
            # create new files
setup
            # Run function to get a list of people
            # in the Secret Santa pool
            # (Set $1 to 0 to indicate that this
            # is the first time around)
get_list 0
            # Read pool list and list people in the
            # pool
echo
echo "Santa List"
echo "~~~~~~~~~~~"

for LINE in $(cat ./SantaList.txt); do
      let l=l+1; echo -n "$l) "
      echo $(echo $LINE | cut -d: -f1)
done
            # If exclusions are active,
            # Read list and print exclusions
if [ $disallow = "yes" ]; then echo; fi
if [ $disallow = "yes" ]; then echo "Disallowed Picks"; fi
if [ $disallow = "yes" ]; then echo "~~~~~~~~~~~~~~~~"; fi
if [ $disallow = "yes" ]; then let -i r=0; fi
if [ $disallow = "yes" ]; then
   for LINE in $(cat ./SantaList.txt); do
      let r=r+1; echo -n "$r) "
      echo -n $(echo $LINE | cut -d: -f1)
      echo -n " cannot pick: "
      echo -n $(echo $LINE | cut -d: -f2)
         if [ -z $(echo $LINE | cut -d: -f2) ]; then
            echo -n "NONE"
         fi
      echo
   done
fi
            # Run function to draw names
            # (Send number of people and round=1)
take_turns $NUMBER 1
            # Cleanup temporary files
rm /var/tmp/SantaHatRandom
rm /var/tmp/SantaHat
            # Random sort names drawn
            # Remove ordered list of names drawn
sort -R /var/tmp/Draws.txt > /var/tmp/DrawsRandom.txt
rm /var/tmp/Draws.txt
            # Print out list of names drawn
            # in random order,
            # Then remove list
echo
echo "Names Drawn (Random Order)"
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~"
cat /var/tmp/DrawsRandom.txt
rm /var/tmp/DrawsRandom.txt
echo
            # Print out list of files in output
            # directory
echo "Output Card Files (Directory: ./SecretSanta)"
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
ls -a ./SecretSanta
echo
            # If "pickcheck" option was selected,
            # Run function to check picks
if [ $pickcheck = "yes" ]; then pickcheck; fi
            # Unless "keep" option was specified,
            # Remove the pool list
if [ $keep = "no" ]; then rm SantaList.txt; fi
            # Report number of rounds taken
            # Report program file and arguments
if [ $verbose = "yes" ]; then echo "[Rounds: $ROUND]"; echo; fi
if [ $verbose = "yes" ]; then echo "$0 $@"; fi
            # Signal end of program
echo "done"; echo


Last edited by gofree on Mon Jan 25, 2010 2:24 am, edited 3 times in total.

Top
 Profile  
 PostPosted: Fri Jan 22, 2010 6:49 am   
User avatar

Joined: Mon Jan 18, 2010 8:10 pm
Posts: 40
Oops, rereading the comments, I noticed quite a few mistakes. :(

Anyway, you get the idea. :)

(Okay, I fixed a few spelling and grammar mistakes. That's better.)


All the best for 2010!
Congratulations and Be Prosperous!
Kung Hei Fat Choi!

<:-P


Top
 Profile  
 PostPosted: Sun Jan 24, 2010 8:19 am   
User avatar

Joined: Mon Jan 18, 2010 8:10 pm
Posts: 40
I suppose that the last thing I want to add to the program is this:
It would be a great feature to be able to attach email addresses to each name in the secretsanta list.
Then when all the names have been picked and emails ($NAME.txt) have been written,
The program would automatically send out the emails to everyone on the list.

I don't know how to send emails from a shell yet, but I am working on it.
Suggestions?


Top
 Profile  
 PostPosted: Mon Jan 25, 2010 2:00 am   
User avatar

Joined: Mon Jan 18, 2010 8:10 pm
Posts: 40
Here is what the program looks like running in normal mode:
Code:
geoffrey@Presario-Laptop:~/Desktop$ secretsanta -x -chk -rm -k
          _______           
       __/       \         
      /           \         
   __/             \_       
  /             \_   \_*** 
/                \___/   *
~~~~~~~~~~~~~~~~~~   *   *
{   Secret Santa   }   *** 
~~~~~~~~~~~~~~~~~~         

Setup
~~~~~

Get List
~~~~~~~~
How many people in list? 6

Please enter name #1: Fred
Enter disallowed name for Fred: Wilma
Please enter name #2: Wilma
Enter disallowed name for Wilma: Fred
Please enter name #3: Pebbles
Enter disallowed name for Pebbles:
Please enter name #4: Barney
Enter disallowed name for Barney: Betty
Please enter name #5: Betty
Enter disallowed name for Betty: Barney
Please enter name #6: Bamm-Bamm
Enter disallowed name for Bamm-Bamm:

Santa List
~~~~~~~~~~~
1) Fred
2) Wilma
3) Pebbles
4) Barney
5) Betty
6) Bamm-Bamm

Disallowed Picks
~~~~~~~~~~~~~~~~
1) Fred cannot pick: Wilma
2) Wilma cannot pick: Fred
3) Pebbles cannot pick: NONE
4) Barney cannot pick: Betty
5) Betty cannot pick: Barney
6) Bamm-Bamm cannot pick: NONE

Drawing
~~~~~~~
Round: 1
1) Fred --> --> Fred.txt
2) Wilma --> --> Wilma.txt
3) Pebbles --> --> Pebbles.txt
4) Barney --> --> Barney.txt
5) Betty --> --> Betty.txt
6) Bamm-Bamm --> --> Bamm-Bamm.txt

Names Drawn (Random Order)
~~~~~~~~~~~~~~~~~~~~~~~~~~
Pebbles
Bamm-Bamm
Barney
Betty
Wilma
Fred

Output Card Files (Directory: ./SecretSanta)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.  ..  Bamm-Bamm.txt  Barney.txt  Betty.txt  Fred.txt  Pebbles.txt  Wilma.txt

Pick Check
~~~~~~~~~~
Santa       Disallow    Card File   Card Name   Pick        Self        Disallowed  Picked Once
~~~~~       ~~~~~~~~    ~~~~~~~~~   ~~~~~~~~~   ~~~~        ~~~~        ~~~~~~~~~~  ~~~~~~~~~~~
Fred        Wilma       yes         yes         yes         no          no          yes         
Wilma       Fred        yes         yes         yes         no          no          yes         
Pebbles     NONE        yes         yes         yes         no          no          yes         
Barney      Betty       yes         yes         yes         no          no          yes         
Betty       Barney      yes         yes         yes         no          no          yes         
Bamm-Bamm   NONE        yes         yes         yes         no          no          yes         

[Errors: 0]

done


In debugging mode, with "verbose" on and "secret" off, the output shows the draws as they are made...
Code:
Drawing
~~~~~~~
Round: 1
1) Fred --> Wilma, Wilma, Fred, Betty --> Fred.txt
2) Wilma --> Wilma, Fred, Fred, Barney --> Wilma.txt
3) Pebbles --> Bamm-Bamm --> Pebbles.txt
4) Barney --> Wilma --> Barney.txt
5) Betty --> Fred --> Betty.txt
6) Bamm-Bamm --> Pebbles --> Bamm-Bamm.txt


...and 'pickcheck' is explicit about the details of output files:
Code:
Pick Check
~~~~~~~~~~
Santa       Disallow    Card File   Card Name   Pick        Self        Disallowed  Picked Once
~~~~~       ~~~~~~~~    ~~~~~~~~~   ~~~~~~~~~   ~~~~        ~~~~        ~~~~~~~~~~  ~~~~~~~~~~~

Fred:Wilma              Fred.txt    Fred        Barney      (Fred)      (Wilma)     Pebbles.txt,
Fred        Wilma       yes         yes         yes         no          no          yes         

Wilma:Fred              Wilma.txt   Wilma       Bamm-Bamm   (Wilma)     (Fred)      Barney.txt,
Wilma       Fred        yes         yes         yes         no          no          yes         

Pebbles:NONE            Pebbles.txt Pebbles     Fred        (Pebbles)   (NONE)      Betty.txt,
Pebbles     NONE        yes         yes         yes         no          no          yes         

Barney:Betty            Barney.txt  Barney      Wilma       (Barney)    (Betty)     Fred.txt,
Barney      Betty       yes         yes         yes         no          no          yes         

Betty:Barney            Betty.txt   Betty       Pebbles     (Betty)     (Barney)    Bamm-Bamm.txt,
Betty       Barney      yes         yes         yes         no          no          yes         

Bamm-Bamm:NON           Bamm-Bamm.t Bamm-Bamm   Betty       (Bamm-Bamm) (NONE)      Wilma.txt,
Bamm-Bamm   NONE        yes         yes         yes         no          no          yes         

[Errors: 0]


If you are wondering why the draws do not match up between examples, it is because I ran the program separate times with different options. :)


Top
 Profile  
 PostPosted: Mon Jan 25, 2010 2:22 am   
User avatar

Joined: Mon Jan 18, 2010 8:10 pm
Posts: 40
A couple of fixes:

This field in 'pickcheck' is truncated too short and should be longer:
Line 424:
printf "%-24.13a" "$LINE" -->
printf "%-24.23s" "$LINE"

Listing output files, it might as well show backup files, if any:
Line 605:
ls ./SecretSanta -->
ls -a ./SecretSanta

(Backup files become relevent when testing the 'pickcheck' function.)


Top
 Profile  
 PostPosted: Mon Jan 25, 2010 11:52 am   
User avatar

Joined: Mon Jan 18, 2010 8:10 pm
Posts: 40
Speaking of using 'pickcheck' for debugging... If everything is working right, the output of the 'pickcheck' function is not very interesting...

But if you set up 'pickcheck' as an independent script and manually alter the 'secretsanta' output files, you can check that 'pickcheck' is accurately verifying the expected output.

Code:
geoffrey@Presario-Laptop:~/Desktop$ pickcheck

Pick Check
~~~~~~~~~~
Santa       Disallow    Card File   Card Name   Pick        Self        Disallowed  Picked Once
~~~~~       ~~~~~~~~    ~~~~~~~~~   ~~~~~~~~~   ~~~~        ~~~~        ~~~~~~~~~~  ~~~~~~~~~~~

Fred:Wilma              NONE        ---         ---         (Fred)      (Wilma)     NONE
Fred        Wilma       NO [1]      ---         ---         ---         ---         NO [2]     

Wilma:Fred              Wilma.txt   Jim         Betty       (Wilma)     (Fred)      NONE
Wilma       Fred        yes         NO [3]      yes         no          no          NO [4]     

Pebbles:NONE            Pebbles.txt Pebbles     Wanda       (Pebbles)   (NONE)      Bamm-Bamm.txt,
Pebbles     NONE        yes         yes         NO [5]      no          no          yes         

Barney:Betty            Barney.txt  Barney      Barney      (Barney)    (Betty)     Barney.txt,Betty.txt,
Barney      Betty       yes         yes         yes         YES [6]     no          NO [7]     

Betty:Barney            Betty.txt   Betty       Barney      (Betty)     (Barney)    Wilma.txt,
Betty       Barney      yes         yes         yes         no          YES [8]     yes         

Bamm-Bamm:NONE          Bamm-Bamm.t Bamm-Bamm   Pebbles     (Bamm-Bamm) (NONE)      NONE
Bamm-Bamm   NONE        yes         yes         yes         no          no          NO [9]     

[Errors: 9]


Of course, you should never see anything like this in normal operation, but it is good to know that the program is checking on itself. Again, because the operator is (quite probably) part of the gift-exchange pool him- or herself and the output is supposed to be secret, the operator cannot check the output. The operator needs to rely on the program to do the checking automatically and accurately. (It would be a real mess, if someone got two gifts and someone else got none.) :((


Top
 Profile  
 PostPosted: Sat Jan 30, 2010 1:11 am   
User avatar

Joined: Mon Jan 18, 2010 8:10 pm
Posts: 40
gofree wrote:
I suppose that the last thing I want to add to the program is this:
It would be a great feature to be able to attach email addresses to each name in the secretsanta list.
Then when all the names have been picked and emails ($NAME.txt) have been written,
The program would automatically send out the emails to everyone on the list.

I don't know how to send emails from a shell yet, but I am working on it.
Suggestions?


Alright, I think I have it covered: I can use 'mutt' with 'ssmtp' to send the output files by gmail. It would be very simple, just:
Code:
mutt -a ./SecretSanta/$SANTA.txt -s "Your Secret Santa Draw" $EMAIL < ./HoHoHo.txt
within a loop that reads an EMAIL for each person (SANTA) on the list ("SantaList.txt"). The file, "HoHoHo.txt", would be a standard email message that goes out to everyone, along with the attachment, "$SANTA.txt", where each person's name and name-of-person-picked are written.

I will probably write it up...
Soon...
But first... I-)


Top
 Profile  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 8 posts ] 

All times are UTC - 6 hours


Who is online

Users browsing this forum: Majestic-12 [Bot] and 5 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Jump to:  
cron


BashScripts | Promote Your Page Too
Powered by phpBB © 2011 phpBB Group
© 2003 - 2011 USA LINUX USERS GROUP