/// <summary>
        /// Redirects to Problem action after successful deletion of the test
        /// </summary>
        /// <param name="id">Id for test to be deleted</param>
        /// <returns>Redirects to /Administration/Tests/Problem/{id} after succesful deletion otherwise to /Administration/Test/ with proper error message</returns>
        public ActionResult ConfirmDelete(int?id)
        {
            if (id == null)
            {
                this.TempData.AddDangerMessage(Resource.Invalid_test);
                return(this.RedirectToAction <TestsController>(x => x.Index()));
            }

            var test = this.Data.Tests.All().FirstOrDefault(t => t.Id == id);

            if (test == null)
            {
                this.TempData.AddDangerMessage(Resource.Invalid_test);
                return(this.RedirectToAction <TestsController>(x => x.Index()));
            }

            if (!this.CheckIfUserHasProblemPermissions(test.ProblemId))
            {
                this.TempData[GlobalConstants.DangerMessage] = "Нямате привилегиите за това действие";
                return(this.RedirectToAction("Index", "Contests", new { area = "Administration" }));
            }

            using (var scope = new TransactionScope())
            {
                // delete all test runs for the test
                this.Data.TestRuns.Delete(tr => tr.TestId == id.Value);
                this.Data.SaveChanges();

                // delete the test
                this.Data.Tests.Delete(test);
                this.Data.SaveChanges();

                // recalculate submissions point
                var problemSubmissions = this.Data.Submissions
                                         .All()
                                         .Include(s => s.TestRuns)
                                         .Include(s => s.TestRuns.Select(tr => tr.Test))
                                         .Where(s => s.ProblemId == test.ProblemId)
                                         .ToList();

                var submissionResults = problemSubmissions
                                        .Select(s => new
                {
                    s.Id,
                    s.ParticipantId,
                    CorrectTestRuns = s.TestRuns.Count(t => t.ResultType == TestRunResultType.CorrectAnswer && !t.Test.IsTrialTest),
                    AllTestRuns     = s.TestRuns.Count(t => !t.Test.IsTrialTest),
                    MaxPoints       = s.Problem.MaximumPoints
                })
                                        .ToList();

                var problemSubmissionsById = problemSubmissions.ToDictionary(s => s.Id);
                var topResults             = new Dictionary <int, ParticipantScoreModel>();

                foreach (var submissionResult in submissionResults)
                {
                    var submission = problemSubmissionsById[submissionResult.Id];
                    int points     = 0;
                    if (submissionResult.AllTestRuns != 0)
                    {
                        points = (submissionResult.CorrectTestRuns * submissionResult.MaxPoints) / submissionResult.AllTestRuns;
                    }

                    submission.Points = points;
                    submission.CacheTestRuns();

                    if (submissionResult.ParticipantId.HasValue)
                    {
                        var participantId = submissionResult.ParticipantId.Value;

                        if (!topResults.ContainsKey(participantId) || topResults[participantId].Points < points)
                        {
                            // score does not exists or have less points than current submission
                            topResults[participantId] = new ParticipantScoreModel
                            {
                                Points       = points,
                                SubmissionId = submission.Id
                            };
                        }
                        else if (topResults[participantId].Points == points)
                        {
                            // save score with latest submission
                            if (topResults[participantId].SubmissionId < submission.Id)
                            {
                                topResults[participantId].SubmissionId = submission.Id;
                            }
                        }
                    }
                }

                this.Data.SaveChanges();

                var participants = topResults.Keys.ToList();

                // find all participant scores for the test's problem
                var existingScores = this.participantScoresData
                                     .GetAll()
                                     .Where(x => x.ProblemId == test.ProblemId && participants.Contains(x.ParticipantId))
                                     .ToList();

                // replace the scores with updated values
                foreach (var existingScore in existingScores)
                {
                    var topScore = topResults[existingScore.ParticipantId];

                    existingScore.Points       = topScore.Points;
                    existingScore.SubmissionId = topScore.SubmissionId;
                }

                this.Data.SaveChanges();

                scope.Complete();
            }

            this.TempData.AddInfoMessage(Resource.Test_deleted_successfully);
            return(this.RedirectToAction("Problem", new { id = test.ProblemId }));
        }
Example #2
0
        public void RecalculatePointsByProblem(int problemId)
        {
            using (var scope = TransactionsHelper.CreateTransactionScope())
            {
                var problemSubmissions = this.submissionsData
                                         .GetAllByProblem(problemId)
                                         .Include(s => s.TestRuns)
                                         .Include(s => s.TestRuns.Select(tr => tr.Test))
                                         .ToList();

                var submissionResults = problemSubmissions
                                        .Select(s => new
                {
                    s.Id,
                    s.ParticipantId,
                    CorrectTestRuns = s.TestRuns.Count(t =>
                                                       t.ResultType == TestRunResultType.CorrectAnswer &&
                                                       !t.Test.IsTrialTest),
                    AllTestRuns = s.TestRuns.Count(t => !t.Test.IsTrialTest),
                    MaxPoints   = s.Problem.MaximumPoints
                })
                                        .ToList();

                var problemSubmissionsById = problemSubmissions.ToDictionary(s => s.Id);
                var topResults             = new Dictionary <int, ParticipantScoreModel>();

                foreach (var submissionResult in submissionResults)
                {
                    var submission = problemSubmissionsById[submissionResult.Id];
                    var points     = 0;
                    if (submissionResult.AllTestRuns != 0)
                    {
                        points = (submissionResult.CorrectTestRuns * submissionResult.MaxPoints) /
                                 submissionResult.AllTestRuns;
                    }

                    submission.Points = points;
                    submission.CacheTestRuns();

                    if (!submissionResult.ParticipantId.HasValue)
                    {
                        continue;
                    }

                    var participantId = submissionResult.ParticipantId.Value;

                    if (!topResults.ContainsKey(participantId) || topResults[participantId].Points < points)
                    {
                        topResults[participantId] = new ParticipantScoreModel
                        {
                            Points       = points,
                            SubmissionId = submission.Id
                        };
                    }
                    else if (topResults[participantId].Points == points)
                    {
                        if (topResults[participantId].SubmissionId < submission.Id)
                        {
                            topResults[participantId].SubmissionId = submission.Id;
                        }
                    }
                }

                this.submissions.SaveChanges();

                var participants = topResults.Keys.ToList();

                var existingScores = this.participantScoresData
                                     .GetAllByProblem(problemId)
                                     .Where(p => participants.Contains(p.ParticipantId))
                                     .ToList();

                foreach (var existingScore in existingScores)
                {
                    var topScore = topResults[existingScore.ParticipantId];

                    existingScore.Points       = topScore.Points;
                    existingScore.SubmissionId = topScore.SubmissionId;
                }

                this.submissions.SaveChanges();

                scope.Complete();
            }
        }