/// <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); }
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; }
// 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(); }
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; }
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); }
/// <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()); } } }
/// <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)); }
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(); }
/// <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); }
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); } } }
/// <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()); } }
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(); }