Quiz a user from a question pool in a txt, tab seperated, spreadsheet.
by deaves
#!/bin/bash
## Created by: deaves
# Quiz a user from a question pool in a txt, tab seperated, spreadsheet.
#
# The following is how to format the rows in the input file:
# ColumnA [Integer]: True Answer (D=0,E=1,F=2,...)
# ColumnB [String]: Answer Number
# ColumnC [String]: Question
# ColumnD+[String]: Answer
#
# FYI: If you have problems try using Open Office to create the spreadsheet,
# MS Office does not properly suround cells with quotes so it gives eval problems.
#
## Requires: dialog (Optional: TTS synthesizer)
## Comment out speakCMD var if no text/speach synth.
#speakCMD="flite -s duration_stretch=0.8"
#speakCMD="xclip -i -selection clipboard"
### Begin Functions ###
function diaSTRING () {
### Retrun no variables; just create a dialog string.
printf "dialog --stdout --backtitle \"${cTALLY}/${qTALLY}:\t${backTITLE}\" \\
--title \"${qArray[1]}\" --menu \'${qArray[2]}\' 0 0 0 "
# Count the total answer elements in the array.
ansNUM=$(expr ${#qArray[@]} - 3)
count=0 # The answer number the user sees.
acount=2 # The true answer element in the array.
# Generate the possible answers.
while [ "${count}" -lt ${ansNUM} ] && [ -n "${qArray[${acount}]}" ]
do
let acount++
printf "${count} \'${qArray[${acount}]}\' "
let count++
done
unset count acount ansNUM # Unset variables.
}
function diaRESULT () {
### Display the test results...
# Display number of questions answered correctly when finished.
if [ -z "${dANS}" -a -z "${REVIEW}" ]; then
dialog --backtitle "${backTITLE}" --title "${quizFILE}" \
--msgbox "You answered:\n ${cTALLY} questions out of ${qTALLY} correct" 0 0
# Display correct answer if the wrong answer was selected.
else
dialog --backtitle "${backTITLE}" --title "${qArray[1]}" \
--msgbox "Q: $(echo "${qArray[2]}")\n\nA: $(echo "${qArray[`expr ${qArray[0]} + 3`]}")" 0 0
fi
}
function pick_Question () {
### Select question and build qArray...
if [ -z ${QUESTION} ]; then
QUESTION=$[ ( ${RANDOM} % ${QUESTIONS} ) + 1 ]
# Do not ask the same question twice...
[ -z ${lastQUESTION} ] && { lastQUESTION=0; }
while [ ${QUESTION} = ${lastQUESTION} ]; do
QUESTION=$[ ( ${RANDOM} % ${QUESTIONS} ) + 1 ]
done
lastQUESTION=${QUESTION} # Remember the previous question.
fi
# Use eval to load the entire row into qArray...
eval qArray=( `sed -n ${QUESTION}'p' "${quizFILE}" | 's/%/%%/g'` )
# Unset the current randomly chosen question.
[ -z ${REVIEW} ] && { unset QUESTION; }
}
function review_Questions () {
### Review each question in the entire pool.
declare -i QUESTION=1
while [ "${QUESTION}" != `expr ${QUESTIONS} + 1` ]; do
pick_Question # Load question into qArray.
dANS="${qArray[0]}" # Set the correct answer.
speakTEXT & # Read Q&A to the user.
diaRESULT # Display Q&A to the user.
unset dANS qArray # Unset variables.
let QUESTION++ # Next question.
done
}
function speakTEXT () {
### Use a text to speach synth to read the question & answer.
## If this function is unwanted leave the speakCMD variable blank.
# Ask the question...
if [ -n "${speakCMD}" ] && [ -z "${dANS}" ]; then
echo "${qArray[2]}" | ${speakCMD}
# Review the question & answer...
elif [ -n "${speakCMD}" ] && [ -n "${REVIEW}" ]; then
echo "Question, ${qArray[1]} . ${qArray[2]}" | ${speakCMD}
echo "The Answer is, $(echo ${qArray[`expr ${qArray[0]} + 3`]})" | ${speakCMD}
# Give the answer...
elif [ -n "${speakCMD}" ]; then
echo "The correct answer was: $(echo ${qArray[`expr ${qArray[0]} + 3`]})" | ${speakCMD}
fi
}
function usage () {
### Display the script arguments.
printf "Usage: $0 -f <file .txt=""> [-rs]\n\n"
printf "Required...\n"
printf "\t-f: Specify the file containing the question pool. (required)\n\n"
printf "Optional...\n"
printf "\t-r: Review all the questions in the pool.\n"
printf "\t-s: Disable sound (if the speakCMD is defined).\n\n"
}
### Get passed arguments. ###
while getopts ":f:rs" ARG; do
case "${ARG}" in
f) quizFILE="${OPTARG}";;
r) REVIEW="Y";;
s) unset speakCMD;;
esac
done
### Display command usage and exit ###
[ -z "${quizFILE}" ] && { usage && exit 1; }
### Variables that should not be changed ###
backTITLE="Dave's cute quiz script."
QUESTIONS=`wc -l "${quizFILE}" | awk '{print $1}'`
qTALLY=0 # Total questions asked...
cTALLY=0 # Total questions correct...
### Review all questions and exit script ###
[ "${REVIEW}" = "Y" ] && { review_Questions; exit 0; }
### Main Loop ###
while true; do
pick_Question # Pick a Question.
speakTEXT & # Read the question.
dANS=`bash -c "$(diaSTRING)"` # Ask question and store response as "dANS".
[ -z "${dANS}" ] && { diaRESULT && break; } # Break out of the loop if user selects cancel.
let qTALLY++ # Tally the total number of questions asked.
if [ ${dANS} == "${qArray[0]}" ]; then ### Response is correct ###
let cTALLY++ # Tally the questions answered correct.
else ### Response is wrong ###
speakTEXT & # Speak the correct answer.
diaRESULT # Show the correct answer.
fi
unset dANS qArray # Unset loop variables at end of pass.
done
### Finish ###