コード例 #1
0
 /// <summary>
 /// Constructor.
 /// </summary>
 public SubmissionCandidatesViewModel(
     User user,
     IList<Commit> commits,
     Func<Commit, string> commitUrlBuilder,
     Checkpoint checkpoint,
     Model.Projects.Submission latestSubmission,
     ITimeZoneProvider timeZoneProvider)
 {
     User = user;
     Checkpoint = checkpoint;
     Candidates = commits
         .OrderByDescending(commit => commit.PushDate)
         .ThenByDescending(commit => commit.CommitDate)
         .Select
         (
             commit => new SubmissionCandidateViewModel
             (
                 commit,
                 commitUrlBuilder(commit),
                 latestSubmission?.CommitId == commit.Id,
                 commit == commits.First(),
                 timeZoneProvider
             )
         ).ToList();
 }
コード例 #2
0
		/// <summary>
		/// Populates a submission branch with a pull request, and returns the 
		/// pull request number.
		/// </summary>
		public async Task<int> CreatePullRequestAsync(
			Commit commit,
			Checkpoint checkpoint)
		{
			var student = GetStudent(commit.Project, commit.User);
			var orgName = student.Classroom.GitHubOrganization;
			var repoName = checkpoint.Project.GetStudentRepoName(student);

			// Get the commits to use in the pull requests.
			var allCommits = await GetAllCommitsAsync(commit.Project, student);
			var submissionCommit = allCommits.SingleOrDefault(c => c.Sha == commit.Sha);
			var startingCommit = allCommits.Where(c => c.Parents.Count == 0)
				.OrderBy(c => c.Date)
				.FirstOrDefault();

			// Create a submission branch that initially just contains the starting commit.
			// This will be the destination of our new pull request.
			var destBranchName = checkpoint.Name;
			await _repoClient.CreateBranchAsync
			(
				orgName, 
				repoName, 
				destBranchName, 
				startingCommit.Sha
			);

			// Create a temporary source branch that initially contains the student's commit 
			// for the checkpoint, and all previous commits. This is the source of the pull request.
			var sourceBranchName = $"{checkpoint.Name}Source";
			await _repoClient.CreateBranchAsync
			(
				orgName,
				repoName,
				sourceBranchName,
				submissionCommit.Sha
			);

			// Create the pull request.
			var pullRequestTitle = $"{checkpoint.DisplayName} Submission";
			int pullRequestNumber = await _repoClient.CreatePullRequestAsync
			(
				orgName,
				repoName,
				pullRequestTitle,
				sourceBranchName,
				destBranchName
			);

			// Delete the temporary source branch.
			await _repoClient.DeleteBranchAsync(orgName, repoName, sourceBranchName);

			return pullRequestNumber;
		}
コード例 #3
0
        /// <summary>
        /// Constructor.
        /// </summary>
        public GradeSubmissionViewModel(
            Checkpoint checkpoint,
            GradeSubmissionResult result,
            Func<TestResult, string> testUrlBuilder,
            Func<int, string> buildUrlBuilder,
            Func<Commit, int, string> pullRequestUrlBuilder,
            ITimeZoneProvider timeZoneProvider)
        {
            LastName = result.LastName;
            FirstName = result.FirstName;
            SubmissionId = result.SubmissionId;

            CommitDate = GetLink
            (
                buildUrlBuilder(result.Build.Id),
                result.CommitDate.FormatShortDateTime(timeZoneProvider),
                preventWrapping: true
            );

            SubmissionStatus = GetSubmissionStatus(result.DaysLate);

            PullRequest = GetLink
            (
                pullRequestUrlBuilder(result.Build.Commit, result.PullRequestNumber.Value),
                "See Submission",
                preventWrapping: true
            );

            RequiredTests = result.RequiredTestsPassed
                ? GetColoredText("green", "Passed", bold: false, preventWrapping: true)
                : GetColoredText("red", "Failed", bold: true, preventWrapping: true);

            Feedback = result.Feedback;
            FeedbackSent = result.FeedbackSent;

            TestClassResults = TestClassTableEntry.GetTestClassResults
            (
                checkpoint,
                result.Build,
                testUrlBuilder
            );

            PastSubmissions = result.PastSubmissions.Select
            (
                pastSubmission => new PastSubmissionTableEntry
                (
                    pastSubmission,
                    buildUrlBuilder,
                    pullRequestUrlBuilder,
                    timeZoneProvider
                )
            ).ToList();
        }
コード例 #4
0
		/// <summary>
		/// Executes before the action is executed.
		/// </summary>
		protected override async Task InitializeAsync()
		{
			await base.InitializeAsync();

			Checkpoint = await CheckpointService.GetCheckpointAsync
			(
				ClassroomName, 
				ProjectName, 
				CheckpointName
			);

			ViewBag.Checkpoint = Checkpoint;
		}
コード例 #5
0
 /// <summary>
 /// Constructor.
 /// </summary>
 public SubmittedViewModel(
     Commit commit,
     string commitUrl,
     Checkpoint checkpoint,
     ITimeZoneProvider timeZoneProvider)
 {
     User = commit.User;
     Checkpoint = checkpoint;
     Submission = new SubmissionCandidateViewModel
     (
         commit,
         commitUrl,
         true /*previousSubmission*/,
         true /*defaultChoice*/,
         timeZoneProvider
     );
 }
コード例 #6
0
		/// <summary>
		/// Creates a checkpoint.
		/// </summary>
		public async Task<bool> CreateCheckpointAsync(
			string classroomName,
			string projectName,
			Checkpoint checkpoint, 
			IModelErrorCollection modelErrors)
		{
			var project = await LoadProjectAsync(classroomName, projectName);

			if (!UpdateCheckpoint(checkpoint, modelErrors))
				return false;

			checkpoint.ProjectId = project.Id;
			_dbContext.Add(checkpoint);

			await _dbContext.SaveChangesAsync();

			return true;
		}
コード例 #7
0
		/// <summary>
		/// Downloads submissions for a set of students.
		/// </summary>
		public async Task<StudentSubmissions> DownloadSubmissionsAsync(
			Checkpoint checkpoint,
			IList<StudentDownloadRequest> studentDownloadRequests)
		{
			var orgName = checkpoint.Project.Classroom.GitHubOrganization;
			var projName = checkpoint.Project.Name;

			var students = studentDownloadRequests
				.Select(request => request.Student)
				.ToList();

			var studentsWithSubmissions = new HashSet<ClassroomMembership>
			(
				studentDownloadRequests
					.Where(request => request.Submitted)
					.Select(request => request.Student)
			);

			var studentRepos = await _repoMetadataRetriever.GetStudentRepositoriesAsync
			(
				checkpoint.Project,
				students
			);

			var submissions = await _operationRunner.RunOperationsAsync
			(
				studentRepos.Keys,
				async student => new StudentSubmission
				(
					student,
					await _repoClient.GetRepositoryContentsAsync
					(
						orgName,
						_repoMetadataRetriever.GetRepoName(checkpoint.Project, student),
						studentsWithSubmissions.Contains(student)
							? checkpoint.Name
							: null,
						ArchiveStore.FileSystem
					)
				)
			);

			return new StudentSubmissions(submissions);
		}
コード例 #8
0
		public async Task<IActionResult> Create(Checkpoint checkpoint)
		{
			if (ModelState.IsValid)
			{
				var succeeded = await CheckpointService.CreateCheckpointAsync
				(
					ClassroomName,
					ProjectName,
					checkpoint,
					ModelErrors
				);

				if (succeeded)
				{
					return RedirectToAction("Index");
				}
			}

			return View("CreateEdit", checkpoint);
		}
コード例 #9
0
		/// <summary>
		/// Returns a query for all submissions in a given checkpoint.
		/// </summary>
		private IQueryable<Submission> GetCheckpointSubmissionsQuery(
			Checkpoint checkpoint,
			Section section)
		{
			return _dbContext.Submissions
				.Where
				(
					submission =>
						submission.CheckpointId == checkpoint.Id &&
						submission.Commit.User.ClassroomMemberships.Any
						(
							cm => cm.SectionMemberships.Any
							(
								sm => sm.SectionId == section.Id
									  && sm.Role == SectionRole.Student
							)
						)
				)
				.Include(submission => submission.Commit.User.ClassroomMemberships)
				.Include(submission => submission.Commit.Build);
		}
コード例 #10
0
		/// <summary>
		/// Returns all submissions for the current checkpoint, along with
		/// submissions for past checkpoints.
		/// </summary>
		private async Task<List<Submission>> GetSubmissionsForGrading(
			Checkpoint checkpoint,
			Section section,
			DateTime dueDate)
		{
			return await _dbContext.Submissions
				.Where
				(
					submission =>
						submission.Checkpoint.ProjectId == checkpoint.ProjectId &&
						submission.Checkpoint
							.SectionDates.First(sd => sd.SectionId == section.Id)
							.DueDate <= dueDate &&
						submission.Commit.User.ClassroomMemberships.Any
						(
							cm => cm.SectionMemberships.Any
							(
								sm => sm.SectionId == section.Id
									  && sm.Role == SectionRole.Student
							)
						)
				)
				.Include(submission => submission.Commit.Build.TestResults)
				.Include(submission => submission.Commit.User.ClassroomMemberships)
				.Include(submission => submission.Checkpoint.SectionDates)
				.ToListAsync();
		}
コード例 #11
0
		/// <summary>
		/// Updates a checkpoint.
		/// </summary>
		public async Task<bool> UpdateCheckpointAsync(
			string classroomName,
			string projectName,
			Checkpoint checkpoint,
			IModelErrorCollection modelErrors)
		{
			var project = await LoadProjectAsync(classroomName, projectName);

			checkpoint.ProjectId = project.Id;

			var currentCheckpoint = await _dbContext.Checkpoints
				.Where(c => c.Id == checkpoint.Id)
				.SingleOrDefaultAsync();

			_dbContext.Entry(currentCheckpoint).State = EntityState.Detached;

			if (!UpdateCheckpoint(checkpoint, modelErrors))
				return false;

			_dbContext.Update(checkpoint);

			await _dbContext.SaveChangesAsync();

			return true;
		}
コード例 #12
0
		/// <summary>
		/// Updates a checkpoint.
		/// </summary>
		private bool UpdateCheckpoint(Checkpoint checkpoint, IModelErrorCollection modelErrors)
		{
			if (checkpoint.SectionDates != null)
			{
				var sections = checkpoint.SectionDates.Select(d => d.SectionId).ToList();
				if (sections.Distinct().Count() != sections.Count)
				{
					modelErrors.AddError("SectionDates", "You may only have one due date per section.");
				}
			}

			if (checkpoint.TestClasses != null)
			{
				var testClasses = checkpoint.TestClasses.Select(tc => tc.TestClassId).ToList();
				if (testClasses.Distinct().Count() != testClasses.Count)
				{
					modelErrors.AddError("TestClasses", "You may only have one entry per test class.");
				}
			}

			if (modelErrors.HasErrors)
			{
				return false;
			}

			_dbContext.RemoveUnwantedObjects
			(
				_dbContext.CheckpointDates,
				checkpointDates => checkpointDates.Id,
				checkpointDates => checkpointDates.CheckpointId == checkpoint.Id,
				checkpoint.SectionDates
			);

			_dbContext.RemoveUnwantedObjects
			(
				_dbContext.CheckpointTestClasses,
				testClass => testClass.Id,
				testClass => testClass.CheckpointId == checkpoint.Id,
				checkpoint.TestClasses
			);

			return true;
		}
コード例 #13
0
        /// <summary>
        /// Returns table entries for each test class.
        /// </summary>
        public static IList<TestClassTableEntry> GetTestClassResults(
            Checkpoint checkpoint,
            Model.Projects.Build build,
            Func<TestResult, string> testUrlBuilder)
        {
            var testClasses = build.Commit.Project.TestClasses;

            return build.TestResults.GroupBy(result => result.ClassName)
                .OrderBy
                (
                    result => testClasses.FirstOrDefault
                    (
                        testClass => testClass.ClassName == result.Key
                    )?.Order ?? 0
                )
                .Where
                (
                    group => testClasses.Any
                    (
                        testClass => testClass.ClassName == group.Key
                    )

                    &&

                    (
                        checkpoint == null ||
                        (
                            checkpoint.TestClasses?.Any
                            (
                                testClass => testClass.TestClass.ClassName == group.Key
                            ) ?? false
                        )
                    )
                )
                .Select
                (
                    group => new TestClassTableEntry
                    (
                        testClasses.Single(testClass => testClass.ClassName == group.Key),
                        checkpoint?.TestClasses
                            ?.FirstOrDefault(tc => tc.TestClass.ClassName == group.Key)
                            ?.Required ?? false,
                        group.ToList(),
                        testUrlBuilder
                    )
                ).ToList();
        }