Exemple #1
0
        /// <summary>
        /// Gets data from the scan item field and shows it.
        /// </summary>
        private void PopulateForm()
        {
            // load scan
            scanPictureBox.Image = ImageHandling.GetBitmap(scanItem.Image);

            // load the answers
            List <KlokanTestDBExpectedAnswer> expectedValues = new List <KlokanTestDBExpectedAnswer>(scanItem.ExpectedValues);

            TableArrayHandling.DbSetToAnswers(expectedValues, out expectedValuesStudentTable, out expectedValuesAnswerTable);

            FormTableHandling.DrawAnswers(studentTablePictureBox, expectedValuesStudentTable, 0, FormTableHandling.DrawCross, Color.Black);
            FormTableHandling.DrawAnswers(answerTable1PictureBox, expectedValuesAnswerTable, 0, FormTableHandling.DrawCross, Color.Black);
            FormTableHandling.DrawAnswers(answerTable2PictureBox, expectedValuesAnswerTable, 1, FormTableHandling.DrawCross, Color.Black);
            FormTableHandling.DrawAnswers(answerTable3PictureBox, expectedValuesAnswerTable, 2, FormTableHandling.DrawCross, Color.Black);

            bool[,,] computedValuesStudentTable;
            bool[,,] computedValuesAnswerTable;

            List <KlokanTestDBComputedAnswer> computedValues = new List <KlokanTestDBComputedAnswer>(scanItem.ComputedValues);

            TableArrayHandling.DbSetToAnswers(computedValues, out computedValuesStudentTable, out computedValuesAnswerTable);

            FormTableHandling.DrawAnswers(studentTablePictureBox, computedValuesStudentTable, 0, FormTableHandling.DrawCircle, Color.Red);
            FormTableHandling.DrawAnswers(answerTable1PictureBox, computedValuesAnswerTable, 0, FormTableHandling.DrawCircle, Color.Red);
            FormTableHandling.DrawAnswers(answerTable2PictureBox, computedValuesAnswerTable, 1, FormTableHandling.DrawCircle, Color.Red);
            FormTableHandling.DrawAnswers(answerTable3PictureBox, computedValuesAnswerTable, 2, FormTableHandling.DrawCircle, Color.Red);
        }
Exemple #2
0
        private void discardButton_Click(object sender, EventArgs e)
        {
            ResetTableImages();

            // draw the original answers
            FormTableHandling.DrawAnswers(studentTablePictureBox, expectedValuesStudentTable, 0, FormTableHandling.DrawCross, Color.Black);
            FormTableHandling.DrawAnswers(answerTable1PictureBox, expectedValuesAnswerTable, 0, FormTableHandling.DrawCross, Color.Black);
            FormTableHandling.DrawAnswers(answerTable2PictureBox, expectedValuesAnswerTable, 1, FormTableHandling.DrawCross, Color.Black);
            FormTableHandling.DrawAnswers(answerTable3PictureBox, expectedValuesAnswerTable, 2, FormTableHandling.DrawCross, Color.Black);

            bool[,,] computedValuesStudentTable;
            bool[,,] computedValuesAnswerTable;

            List <KlokanTestDBComputedAnswer> computedValues = new List <KlokanTestDBComputedAnswer>(scanItem.ComputedValues);

            TableArrayHandling.DbSetToAnswers(computedValues, out computedValuesStudentTable, out computedValuesAnswerTable);

            FormTableHandling.DrawAnswers(studentTablePictureBox, computedValuesStudentTable, 0, FormTableHandling.DrawCircle, Color.Red);
            FormTableHandling.DrawAnswers(answerTable1PictureBox, computedValuesAnswerTable, 0, FormTableHandling.DrawCircle, Color.Red);
            FormTableHandling.DrawAnswers(answerTable2PictureBox, computedValuesAnswerTable, 1, FormTableHandling.DrawCircle, Color.Red);
            FormTableHandling.DrawAnswers(answerTable3PictureBox, computedValuesAnswerTable, 2, FormTableHandling.DrawCircle, Color.Red);

            editButton.Enabled    = true;
            applyButton.Enabled   = false;
            discardButton.Enabled = false;
            viewMode = true;
        }
Exemple #3
0
        // save the batch and close the form
        private void saveButton_Click(object sender, EventArgs e)
        {
            for (int i = 0; i < 3; i++)
            {
                if (!TableArrayHandling.CheckAnswers(correctAnswers, i))
                {
                    MessageBox.Show(Properties.Resources.ErrorTextCorrectAnswersNotSelected, Properties.Resources.ErrorCaptionGeneral,
                                    MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }
            }

            if (answerSheetFilenames.Count == 0)
            {
                MessageBox.Show(Properties.Resources.ErrorTextNoAnswerSheetsSelected, Properties.Resources.ErrorCaptionGeneral,
                                MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            categoryBatch.CorrectAnswers = correctAnswers;
            categoryBatch.SheetFilenames = answerSheetFilenames;

            DialogResult = DialogResult.OK;
            this.Close();
        }
Exemple #4
0
        private void applyButton_Click(object sender, EventArgs e)
        {
            if (addMode && (scanFilePath == null || scanFilePath == ""))
            {
                MessageBox.Show(Properties.Resources.ErrorTextNoFileSelected, Properties.Resources.ErrorCaptionGeneral,
                                MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            if (!TableArrayHandling.CheckAnswers(expectedValuesStudentTableTemp, 0))
            {
                MessageBox.Show(Properties.Resources.ErrorTextStudentNumberNotSelected, Properties.Resources.ErrorCaptionGeneral,
                                MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            for (int i = 0; i < 3; i++)
            {
                if (!TableArrayHandling.CheckAnswers(expectedValuesAnswerTableTemp, i))
                {
                    MessageBox.Show(Properties.Resources.ErrorTextExpectedAnswersNotSelected, Properties.Resources.ErrorCaptionGeneral,
                                    MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }
            }

            // apply the changes
            expectedValuesStudentTable = expectedValuesStudentTableTemp;
            expectedValuesAnswerTable  = expectedValuesAnswerTableTemp;

            // draw the computed answers for comparison (if there are any)
            bool[,,] computedValuesStudentTable;
            bool[,,] computedValuesAnswerTable;

            List <KlokanTestDBComputedAnswer> computedValues = new List <KlokanTestDBComputedAnswer>(scanItem.ComputedValues);

            TableArrayHandling.DbSetToAnswers(computedValues, out computedValuesStudentTable, out computedValuesAnswerTable);

            FormTableHandling.DrawAnswers(studentTablePictureBox, computedValuesStudentTable, 0, FormTableHandling.DrawCircle, Color.Red);
            FormTableHandling.DrawAnswers(answerTable1PictureBox, computedValuesAnswerTable, 0, FormTableHandling.DrawCircle, Color.Red);
            FormTableHandling.DrawAnswers(answerTable2PictureBox, computedValuesAnswerTable, 1, FormTableHandling.DrawCircle, Color.Red);
            FormTableHandling.DrawAnswers(answerTable3PictureBox, computedValuesAnswerTable, 2, FormTableHandling.DrawCircle, Color.Red);

            updateButton.Enabled  = true;
            editButton.Enabled    = true;
            applyButton.Enabled   = false;
            discardButton.Enabled = false;
            viewMode = true;
        }
Exemple #5
0
        private void reevaluateButton_Click(object sender, EventArgs e)
        {
            reevaluateButton.Enabled     = false;
            updateDatabaseButton.Enabled = true;

            points = TableArrayHandling.CountScore(chosenAnswers, correctAnswers);
            pointsValueLabel.Text = points.ToString();

            // draw both chosen and correct answers again
            ResetTableImages();

            FormTableHandling.DrawAnswers(table1PictureBox, chosenAnswers, 0, FormTableHandling.DrawCross, Color.Black);
            FormTableHandling.DrawAnswers(table2PictureBox, chosenAnswers, 1, FormTableHandling.DrawCross, Color.Black);
            FormTableHandling.DrawAnswers(table3PictureBox, chosenAnswers, 2, FormTableHandling.DrawCross, Color.Black);

            FormTableHandling.DrawAnswers(table1PictureBox, correctAnswers, 0, FormTableHandling.DrawCircle, Color.Red);
            FormTableHandling.DrawAnswers(table2PictureBox, correctAnswers, 1, FormTableHandling.DrawCircle, Color.Red);
            FormTableHandling.DrawAnswers(table3PictureBox, correctAnswers, 2, FormTableHandling.DrawCircle, Color.Red);
        }
Exemple #6
0
        /// <summary>
        /// Asynchronously stores test results into a database described by KlokanTestDBContext.
        /// Results that already exist in the database are rewritten.
        /// </summary>
        /// <param name="results">Any enumerable structure of evaluation test results.</param>
        /// <returns>A void task.</returns>
        async Task OutputTestResultsDB(IEnumerable <TestResult> testResults)
        {
            using (var testDB = new KlokanTestDBContext())
            {
                foreach (var testResult in testResults)
                {
                    if (testResult.Error == true)
                    {
                        failedSheets++;
                        continue;
                    }

                    var scanQuery = from scan in testDB.Scans
                                    where scan.ScanId == testResult.ScanId
                                    select scan;

                    var oldComputedAnswersQuery = from answer in testDB.ComputedValues
                                                  where answer.ScanId == testResult.ScanId
                                                  select answer;

                    // delete old computed values
                    foreach (var answer in oldComputedAnswersQuery)
                    {
                        testDB.ComputedValues.Remove(answer);
                    }

                    // assign new computed values
                    KlokanTestDBScan correspondingScan = scanQuery.FirstOrDefault();

                    var computedValuesDbSet = new List <KlokanTestDBComputedAnswer>();
                    computedValuesDbSet.AddRange(TableArrayHandling.AnswersToDbSet <KlokanTestDBComputedAnswer>(testResult.StudentComputedValues, 0, true));
                    for (int i = 0; i < 3; i++)
                    {
                        computedValuesDbSet.AddRange(TableArrayHandling.AnswersToDbSet <KlokanTestDBComputedAnswer>(testResult.AnswerComputedValues, i, false));
                    }

                    correspondingScan.ComputedValues = computedValuesDbSet;
                    correspondingScan.Correctness    = testResult.Correctness;

                    await testDB.SaveChangesAsync(progressDialog.GetCancellationToken());
                }
            }
        }
Exemple #7
0
        /// <summary>
        /// Evaluates answers contained in an image of an answer sheet against a set of correct answers.
        /// </summary>
        /// <param name="sheetFilename">The path to the image containing answers to be evaluated.</param>
        /// <param name="correctAnswers">Correct answers to evaluate against.</param>
        /// <param name="category">The category this sheet belongs to.</param>
        /// <param name="year">The year this sheet belongs to.</param>
        /// <exception cref="InvalidOperationException">Thrown when the correct answers haven't been loaded prior to the execution of this function.</exception>
        public Result Evaluate(string sheetFilename, bool[,,] correctAnswers, string category, int year)
        {
            if (correctAnswers == null)
            {
                throw new InvalidOperationException(Properties.Resources.ExceptionTextCorrectAnswersNotLoaded);
            }

            // get the answers from the sheet
            bool[,,] studentNumberAnswers;
            bool[,,] answers;
            if (ExtractAnswers(sheetFilename, out studentNumberAnswers, out answers) == false)
            {
                return(new Result(true));
            }

            // get the student number
            int studentNumber = StudentTableToNumber(studentNumberAnswers);

            // count the score
            int score = TableArrayHandling.CountScore(answers, correctAnswers);

            return(new Result(year, category, studentNumber, answers, correctAnswers, score, sheetFilename, false));
        }
Exemple #8
0
        private void updateButton_Click(object sender, EventArgs e)
        {
            var dialogResult = MessageBox.Show(Properties.Resources.PromptTextDatabaseUpdate, Properties.Resources.PromptCaptionDatabaseUpdate,
                                               MessageBoxButtons.YesNo, MessageBoxIcon.Question);

            if (dialogResult == DialogResult.No)
            {
                return;
            }

            updateButton.Enabled = false;

            // prepare the DbSet of chosen expected answers
            List <KlokanTestDBExpectedAnswer> expectedAnswers = new List <KlokanTestDBExpectedAnswer>();

            expectedAnswers.AddRange(TableArrayHandling.AnswersToDbSet <KlokanTestDBExpectedAnswer>(expectedValuesStudentTable, 0, true));
            for (int i = 0; i < 3; i++)
            {
                expectedAnswers.AddRange(TableArrayHandling.AnswersToDbSet <KlokanTestDBExpectedAnswer>(expectedValuesAnswerTable, i, false));
            }

            if (addMode)
            {
                scanItem.Image = ImageHandling.GetImageBytes(scanFilePath, ImageFormat.Png);
            }

            scanItem.ExpectedValues = expectedAnswers;
            scanItem.Correctness    = -1;               // correctness will only have a valid value once the evaluation is run

            using (var testDB = new KlokanTestDBContext())
            {
                // when editing an item we first have to delete the old one
                if (!addMode)
                {
                    var oldScanItemQuery = from scan in testDB.Scans
                                           where scan.ScanId == scanItem.ScanId
                                           select scan;

                    var oldExpectedAnswers = from answer in testDB.ExpectedValues
                                             where answer.ScanId == scanItem.ScanId
                                             select answer;

                    // delete the old expected answers
                    foreach (var answer in oldExpectedAnswers)
                    {
                        testDB.ExpectedValues.Remove(answer);
                    }

                    // assign new expected answers
                    var oldScanItem = oldScanItemQuery.FirstOrDefault();
                    oldScanItem.ExpectedValues = scanItem.ExpectedValues;
                    oldScanItem.Correctness    = -1;
                }
                else
                {
                    KlokanTestDBScan newScanItem = new KlokanTestDBScan
                    {
                        ExpectedValues = scanItem.ExpectedValues,
                        ComputedValues = scanItem.ComputedValues,
                        Image          = scanItem.Image,
                        Correctness    = -1
                    };

                    testDB.Scans.Add(newScanItem);
                }

                try
                {
                    testDB.SaveChanges();

                    MessageBox.Show(Properties.Resources.InfoTextDatabaseUpdated, Properties.Resources.InfoCaptionDatabaseUpdated,
                                    MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
                catch (Exception ex) when(ex is DbUpdateException || ex is DbUpdateConcurrencyException)
                {
                    MessageBox.Show(Properties.Resources.ErrorTextDatabase, Properties.Resources.ErrorCaptionGeneral, MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }

            PopulateForm();
        }
Exemple #9
0
        /// <summary>
        /// Extract answer sheet data from the database and display it in the form.
        /// Returns false if data could not be loaded.
        /// </summary>
        private bool PopulateForm()
        {
            using (var db = new KlokanDBContext())
            {
                // load sheet data
                var sheetQuery = from sheet in db.AnswerSheets
                                 where sheet.AnswerSheetId == answerSheetId
                                 select sheet;

                KlokanDBAnswerSheet answerSheet = sheetQuery.FirstOrDefault();
                if (answerSheet == null)
                {
                    MessageBox.Show(Properties.Resources.ErrorTextSheetNotFoundInDatabase, Properties.Resources.ErrorCaptionGeneral,
                                    MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return(false);
                }

                var instanceQuery = from instance in db.Instances
                                    where instance.InstanceId == answerSheet.InstanceId
                                    select instance;

                KlokanDBInstance currentInstance = instanceQuery.FirstOrDefault();
                if (answerSheet == null)
                {
                    MessageBox.Show(Properties.Resources.ErrorTextSheetNotFoundInDatabase, Properties.Resources.ErrorCaptionGeneral,
                                    MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return(false);
                }

                studentNumber = answerSheet.StudentNumber;

                // show sheet data
                studentNumberValueLabel.Text = answerSheet.StudentNumber.ToString();
                idValueLabel.Text            = answerSheet.AnswerSheetId.ToString();
                yearValueLabel.Text          = currentInstance.Year.ToString();
                categoryValueLabel.Text      = currentInstance.Category.ToString();
                pointsValueLabel.Text        = answerSheet.Points.ToString();

                // load scan
                scanPictureBox.Image = ImageHandling.GetBitmap(answerSheet.Scan);

                // load answers and draw them
                var chosenAnswersQuery = from chosenAnswer in db.ChosenAnswers
                                         where chosenAnswer.AnswerSheetId == answerSheetId
                                         select chosenAnswer;

                var chosenAnswersList = chosenAnswersQuery.ToList();
                if (chosenAnswersList.Count == 0)
                {
                    MessageBox.Show(Properties.Resources.ErrorTextSheetNotFoundInDatabase, Properties.Resources.ErrorCaptionGeneral,
                                    MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return(false);
                }

                TableArrayHandling.DbSetToAnswers(chosenAnswersList, out chosenAnswers);

                FormTableHandling.DrawAnswers(table1PictureBox, chosenAnswers, 0, FormTableHandling.DrawCross, Color.Black);
                FormTableHandling.DrawAnswers(table2PictureBox, chosenAnswers, 1, FormTableHandling.DrawCross, Color.Black);
                FormTableHandling.DrawAnswers(table3PictureBox, chosenAnswers, 2, FormTableHandling.DrawCross, Color.Black);

                var correctAnswersQuery = from correctAnswer in db.CorrectAnswers
                                          where correctAnswer.InstanceId == answerSheet.InstanceId
                                          select correctAnswer;

                var correctAnswersList = correctAnswersQuery.ToList();
                if (correctAnswersList.Count == 0)
                {
                    MessageBox.Show(Properties.Resources.ErrorTextSheetNotFoundInDatabase, Properties.Resources.ErrorCaptionGeneral,
                                    MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return(false);
                }

                TableArrayHandling.DbSetToAnswers(correctAnswersQuery.ToList(), out correctAnswers);

                FormTableHandling.DrawAnswers(table1PictureBox, correctAnswers, 0, FormTableHandling.DrawCircle, Color.Red);
                FormTableHandling.DrawAnswers(table2PictureBox, correctAnswers, 1, FormTableHandling.DrawCircle, Color.Red);
                FormTableHandling.DrawAnswers(table3PictureBox, correctAnswers, 2, FormTableHandling.DrawCircle, Color.Red);
            }

            return(true);
        }
Exemple #10
0
        private void updateDatabaseButton_Click(object sender, EventArgs e)
        {
            updateDatabaseButton.Enabled = false;

            var dialogResult = MessageBox.Show(Properties.Resources.PromptTextDatabaseUpdate, Properties.Resources.PromptCaptionDatabaseUpdate,
                                               MessageBoxButtons.YesNo, MessageBoxIcon.Question);

            if (dialogResult == DialogResult.No)
            {
                return;
            }

            // convert the chosen answers into a DbSet
            List <KlokanDBChosenAnswer> newChosenAnswers = new List <KlokanDBChosenAnswer>();

            for (int i = 0; i < 3; i++)
            {
                newChosenAnswers.AddRange(TableArrayHandling.AnswersToDbSet <KlokanDBChosenAnswer>(chosenAnswers, i, false));
            }

            int newPoints = points;

            using (var db = new KlokanDBContext())
            {
                var query = from sheet in db.AnswerSheets
                            where sheet.AnswerSheetId == answerSheetId
                            select sheet;

                KlokanDBAnswerSheet answerSheet = query.FirstOrDefault();
                if (answerSheet == null)
                {
                    MessageBox.Show(Properties.Resources.ErrorTextSheetNotFoundInDatabase, Properties.Resources.ErrorCaptionGeneral,
                                    MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }

                // load the old chosen answers so that EF knows it should delete them when the old answer sheet is deleted
                List <KlokanDBChosenAnswer> blah = new List <KlokanDBChosenAnswer>(answerSheet.ChosenAnswers);

                KlokanDBAnswerSheet updatedAnswerSheet = new KlokanDBAnswerSheet
                {
                    StudentNumber = studentNumber,
                    Points        = newPoints,
                    Scan          = answerSheet.Scan,
                    InstanceId    = answerSheet.InstanceId,
                    Instance      = answerSheet.Instance,
                    ChosenAnswers = newChosenAnswers
                };

                db.AnswerSheets.Remove(answerSheet);
                db.AnswerSheets.Add(updatedAnswerSheet);

                try
                {
                    db.SaveChanges();

                    MessageBox.Show(Properties.Resources.InfoTextDatabaseUpdated, Properties.Resources.InfoCaptionDatabaseUpdated,
                                    MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
                catch (Exception ex) when(ex is DbUpdateException || ex is DbUpdateConcurrencyException)
                {
                    MessageBox.Show(Properties.Resources.ErrorTextDatabase, Properties.Resources.ErrorCaptionGeneral, MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
        }
Exemple #11
0
        /// <summary>
        /// Asynchronously stores results into a database described by KlokanDBContext.
        /// Instances that already exist in the database are rewritten.
        /// </summary>
        /// <param name="results">Any enumerable structure of evaluation results.</param>
        /// <returns>A void task.</returns>
        async Task OutputResultsDB(IEnumerable <Result> results)
        {
            using (var db = new KlokanDBContext())
            {
                foreach (var result in results)
                {
                    if (result.Error == true)
                    {
                        failedSheets++;
                        continue;
                    }

                    // find out if the instance this result belongs to is new or if it already exists
                    var query = from instance
                                in db.Instances
                                where instance.Year == result.Year && instance.Category == result.Category
                                select instance;

                    KlokanDBInstance currentInstance = query.FirstOrDefault();

                    // if the instance isn't saved in the database
                    if (currentInstance == default(KlokanDBInstance))
                    {
                        // try to search locally too (maybe the instance was added in the previous loop cycle)
                        var querylocal = from instance
                                         in db.Instances.Local
                                         where instance.Year == result.Year && instance.Category == result.Category
                                         select instance;

                        currentInstance = querylocal.FirstOrDefault();
                    }
                    else
                    {
                        // remove it completely because the new one will rewrite it
                        // lazy loading is used, so we need to load all the relations of an instance if we want Remove() to remove those as well
                        var blah  = currentInstance.AnswerSheets;
                        var blah2 = currentInstance.CorrectAnswers;
                        List <ICollection <KlokanDBChosenAnswer> > blah3 = new List <ICollection <KlokanDBChosenAnswer> >();
                        foreach (var answerSheetBlah in blah)
                        {
                            blah3.Add(answerSheetBlah.ChosenAnswers);
                        }

                        db.Instances.Remove(currentInstance);
                        await db.SaveChangesAsync(progressDialog.GetCancellationToken());

                        currentInstance = null;
                    }

                    // if the instance doesn't exist locally either
                    if (currentInstance == default(KlokanDBInstance))
                    {
                        List <KlokanDBCorrectAnswer> correctAnswers = new List <KlokanDBCorrectAnswer>();
                        for (int i = 0; i < 3; i++)
                        {
                            correctAnswers.AddRange(TableArrayHandling.AnswersToDbSet <KlokanDBCorrectAnswer>(result.CorrectAnswers, i, false));
                        }

                        currentInstance = new KlokanDBInstance
                        {
                            Year           = result.Year,
                            Category       = result.Category,
                            CorrectAnswers = correctAnswers
                        };

                        db.Instances.Add(currentInstance);
                    }

                    List <KlokanDBChosenAnswer> chosenAnswers = new List <KlokanDBChosenAnswer>();
                    for (int i = 0; i < 3; i++)
                    {
                        chosenAnswers.AddRange(TableArrayHandling.AnswersToDbSet <KlokanDBChosenAnswer>(result.ChosenAnswers, i, false));
                    }

                    var answerSheet = new KlokanDBAnswerSheet
                    {
                        StudentNumber = result.StudentNumber,
                        Points        = result.Score,
                        ChosenAnswers = chosenAnswers,
                        Scan          = ImageHandling.GetImageBytes(result.SheetFilename, ImageFormat.Png)
                    };

                    currentInstance.AnswerSheets.Add(answerSheet);
                }

                await db.SaveChangesAsync(progressDialog.GetCancellationToken());
            }
        }
Exemple #12
0
        private void evaluateButton_Click(object sender, EventArgs e)
        {
            if (MessageBox.Show(Properties.Resources.PromptTextEvaluationStart, Properties.Resources.PromptCaptionEvaluationStart,
                                MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.No)
            {
                return;
            }

            List <TestKlokanInstance> testInstances = new List <TestKlokanInstance>();

            // get all available test instances
            using (var testDB = new KlokanTestDBContext())
            {
                var allScansQuery = from scan in testDB.Scans
                                    select scan;

                foreach (var scan in allScansQuery)
                {
                    bool[,,] studentExpectedValues;
                    bool[,,] answerExpectedValues;
                    TableArrayHandling.DbSetToAnswers(new List <KlokanTestDBExpectedAnswer>(scan.ExpectedValues), out studentExpectedValues, out answerExpectedValues);

                    TestKlokanInstance testInstance = new TestKlokanInstance {
                        ScanId = scan.ScanId,
                        Image  = scan.Image,
                        StudentExpectedValues = studentExpectedValues,
                        AnswerExpectedValues  = answerExpectedValues
                    };

                    testInstances.Add(testInstance);
                }
            }

            if (testInstances.Count == 0)
            {
                MessageBox.Show(Properties.Resources.InfoTextNoTestItems, Properties.Resources.InfoCaptionNoTestItems,
                                MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }

            TestKlokanBatch testBatch = new TestKlokanBatch {
                Parameters    = chosenParameters,
                TestInstances = testInstances
            };

            ProgressDialog progressDialog = new ProgressDialog(new CancellationTokenSource());

            progressDialog.SetProgressLabel(ProgressBarState.Evaluating);

            var jobScheduler = new JobScheduler(testBatch, progressDialog);

            // new thread created, so that all tasks in it are planned in the threadpool and not in the WinForms synchronization context
            Thread thread = new Thread(jobScheduler.Run);

            thread.IsBackground = true;
            thread.Start();

            progressDialog.StartPosition = FormStartPosition.CenterScreen;
            progressDialog.ShowDialog();

            PopulateDataView();
            ShowAverageCorrectness();
        }