/// <summary>
        /// Jonathan Sanborn
        /// 
        /// Generates Problems based on the current ProblemSet
        /// </summary>
        /// <returns>The Problems generated from the ProblemSet</returns>
       public List<Problem> GenerateProblems()
        {

            if (problemSet.OperandsRange.Count == NUM_OPERANDS)
            {
                int[] number = new int[NUM_OPERANDS];

                for (int i = 0; i < problemSet.NumberOfProblems; i++)
                {

                    for (int j = 0; j < NUM_OPERANDS; j++)
                    {
                        number[j] = rand.Next(problemSet.OperandsRange[j].rangeMin, problemSet.OperandsRange[j].rangeMax);

                        if (problemSet.Operation == Operation.Addition && !problemSet.AllowNegativeProblem)
                        {
                            int count = 0;
                            while (number[j] < 0 && count < NUM_TRIES)
                            {
                                number[j] = rand.Next(problemSet.OperandsRange[j].rangeMin, problemSet.OperandsRange[j].rangeMax);
                                count++;
                                if (count == NUM_TRIES)
                                { number[j] = problemSet.OperandsRange[j].rangeMax; }
                            }
                        }

                        if (j > 0 && problemSet.Operation == Operation.Subtraction && !problemSet.AllowNegativeResult)
                        {
                            if (number[j - 1] - number[j] < 0)
                            {
                                number[j] = nonNegativeResult(number[j - 1], problemSet.OperandsRange[j]);
                            }
                        }

                        if (j > 0 && problemSet.Operation == Operation.Division && number[j] == 0)
                        {
                            number[j] = nonZeroDenominator(problemSet.OperandsRange[j]);
                        }

                        if (j > 0 && problemSet.Operation == Operation.Division && problemSet.WholeNumbersOnly && number[j-1] % number[j] > 0)
                        {
                            WholeNumberResult(ref number[j-1], ref number[j], problemSet.OperandsRange[j]);
                        }

                    }   

                    Problem p = null;
                    for (int k = 1; k < NUM_OPERANDS; k++)
                    {
                        if (p != null)
                        {
                            p = new Problem(problemSet.Operation, p, number[k]);
                        }
                        else
                        {
                            p = new Problem(problemSet.Operation, number[0], number[k]);
                        }
                        problemList.Add(p);
                    }

                }
            }

            return problemList;
        }
        /// <summary>
        /// 9 April 2014
        /// Jonathan Sanborn
        /// 
        /// Get the next problem in the assignment session
        /// </summary>
        /// <param name="answer">The Answer to the current problem</param>
        /// <returns>The next math problem based on the Assignments rules</returns>
        public Problem GetNextProblem(double answer)
        {
            if (!sessionRunning)
            {StartSession();}
            
            if (CurrentProblem.isCorrect(answer))
            {
                problemsCorrect++;
                attemptsRemaining = (int) Assignment.ProblemSet.NumberOfAttempts;

                OnCorrect(EventArgs.Empty);

                if (problemList.Count <= 0)
                {
                    currentProblem = null;
                }
                else
                {
                    ProblemNumber++;
                    currentProblem = problemList.First();
                    problemList.Remove(CurrentProblem);
                }
            }
            else if (attemptsRemaining <= 0 && Assignment.ProblemSet.NumberOfAttempts > 0)
            {
                problemsIncorrect++;
                attemptsRemaining = (int)Assignment.ProblemSet.NumberOfAttempts;

                OnIncorrect(EventArgs.Empty);

                if (problemList.Count <= 0)
                {
                    currentProblem = null;
                }
                else
                {
                    ProblemNumber++;
                    currentProblem = problemList.First();
                    problemList.Remove(CurrentProblem);
                }

            }
            else
            {
                OnIncorrectAttemptsRemaining(EventArgs.Empty);
            }
       
            attemptsRemaining--;
            return CurrentProblem;
        }
        /// <summary>
        /// 9 April 2014
        /// Jonathan Sanborn
        /// 
        /// Constructor for an Assignment Session
        /// </summary>
        /// <param name="mmControl">The Control Object</param>
        /// <param name="assign">The Assignment for this session</param>
        public AssignmentSession(MMControl mmControl, ref Assignment assign)
        {
            init();
            MMControl = mmControl;
            assignment = assign;
            problemSetGenerator = new ProblemSetGenerator(assignment.ProblemSet);
            assignmentAttempt = new AssignmentAttempt();
            problemList = problemSetGenerator.GetProblemList;

            attemptsRemaining = (int)Assignment.ProblemSet.NumberOfAttempts;
            currentProblem = problemList.First();
            problemList.Remove(CurrentProblem);
        }
 /// <summary>
 /// 2 April 204
 /// Jonathan Sanborn
 /// 
 /// Constructor for chaining problems together
 /// </summary>
 /// <param name="operation">The operation this problem preforms</param>
 /// <param name="problem">The problem that contains the result that will act as the first operand of this equation</param>
 /// <param name="operand2">the second operand in the equation</param>
 internal Problem(Operation operation, Problem problem, int operand2)
 {
     init();
     this.Operation = operation;
     this.Operand1 = problem.Answer();
     this.Operand2 = operand2;
 }
        /// <summary> 
        /// Be handed control by CtrlStudnt object
        /// </summary>
        /// <author> Jeff Bunce </author>
        internal void TakeControl()
        {
            assignedDrill = loggedInStudent.Assignments.Where(w => !w.IsCompleted).First();

            problemSetGenerator = new ProblemSetGenerator(assignedDrill.ProblemSet);
            problemSet = assignedDrill.ProblemSet;
            problemList = problemSetGenerator.GetProblemList;
            attemptsRemaining = (int)assignedDrill.ProblemSet.NumberOfAttempts;
            currentProblem = problemList.First();
            problemList.Remove(CurrentProblem);
            ProblemNumber = 1;
            ProblemsCorrect = 0;
            ProblemsIncorrect = 0;
            sessionRunning = false;

            

            switch (problemSet.Operation.ToString())
            {
                case "Addition":
                    operationIndex = 1;
                    break;
                case "Subtraction":
                    operationIndex = 2;
                    break;
                case "Multiplication":
                    operationIndex = 3;
                    break;
                case "Division":
                    operationIndex = 4;
                    break;
                default:
                    operationIndex = 0;
                    break;
            }

            studentDrillForm.DisplayProblem(problemSet.NumberOfProblems.ToString(), (problemNumber).ToString(), operationIndex,
                currentProblem.Operand1.ToString(), currentProblem.Operand2.ToString());
            studentDrillForm.DisplayFeedback(String.Empty); // feedback given upon giving an answer

            studentDrillForm.ShowDialog();
        }
        /// <summary>
        /// 26 April 2014
        /// Jeff Bunce
        /// 
        /// Evaluate correctness and create the appropriate signal
        /// (This is the wrapper for use case sequence)
        /// </summary>
        /// <param name="answer">The Answer to the current problem</param>
        /// <returns>Whether or not</returns>
        private void ProcessAnswer(double answer)
        {
            attemptsRemaining--;
            if (!sessionRunning)
            { StartSession(); }

            // get the current state of the drill
            bool correct = CurrentProblem.isCorrect(answer);
            bool drillComplete = (problemList.Count() < 1);


            string feedback;
            // Give feedback and update grades
            if ((!correct) && (attemptsRemaining > 0))
            {
                feedback = CreateFeedback("IncorrectAttemptsRemaining");
                // give feedback of incorrect-ness
            }
            else if ((!correct) && (attemptsRemaining <= 0))
            {
                feedback = CreateFeedback("Incorrect");

                problemNumber++;
                if (!drillComplete)
                {
                    currentProblem = problemList.First();
                    problemList.Remove(CurrentProblem);
                }
            }
            else // if (correct)
            {
                feedback = CreateFeedback("Correct");
                problemsCorrect++;
                problemNumber++;
                 if (!drillComplete)
                {
                    currentProblem = problemList.First();
                    problemList.Remove(CurrentProblem);
                }
            }


            //// Remove current problem from the list if done with it
            //if ((!drillComplete) && (correct || (attemptsRemaining <= 0))) // problem when attemptsRemaining decremented to 0
            //{
            //    currentProblem = problemList.First();
            //    problemList.Remove(CurrentProblem);
            //}


            studentDrillForm.DisplayFeedback(feedback);


            if (drillComplete)
            {
                GradeSession();
                FileHandler.SaveNewAssignmentAttempt(assignmentAttempt);
                studentDrillForm.Hide();
                studentDrillForm.Close();

                DisplayResults();
                ShowResultsScreen();
            }
            else
            {
                DisplayProblem(problemSet.NumberOfProblems.ToString(), problemNumber.ToString(), operationIndex,
                     currentProblem.Operand1.ToString(), currentProblem.Operand2.ToString());
            }
        }