private async Task <bool> TrySendSubmissionResultsToQueue(XQueueClient client, XQueueExerciseSubmission submission) { var checking = submission.Submission.AutomaticChecking; var slide = (await courseManager.FindCourseAsync(checking.CourseId))?.FindSlideById(checking.SlideId, true) as ExerciseSlide; if (slide == null) { log.Warn($"Can't find exercise slide {checking.SlideId} in course {checking.CourseId}. Exit"); return(false); } var score = checking.IsRightAnswer ? 1 : 0; var message = checking.IsCompilationError ? checking.CompilationError.Text : checking.Output.Text; return(await client.PutResult(new XQueueResult { header = submission.XQueueHeader, Body = new XQueueResultBody { IsCorrect = checking.IsRightAnswer, Message = message, Score = score, } })); }
private async Task <RunnerSubmission> ToRunnerSubmission(UserExerciseSubmission submission, IWebCourseManager courseManager) { log.Info($"Собираю для отправки в RunCsJob решение {submission.Id}"); var slide = (await courseManager.FindCourseAsync(submission.CourseId))?.FindSlideById(submission.SlideId, true); if (slide is ExerciseSlide exerciseSlide) { log.Info($"Ожидаю, если курс {submission.CourseId} заблокирован"); courseManager.WaitWhileCourseIsLocked(submission.CourseId); log.Info($"Курс {submission.CourseId} разблокирован"); if (exerciseSlide is PolygonExerciseSlide) { return(((PolygonExerciseBlock)exerciseSlide.Exercise).CreateSubmission( submission.Id.ToString(), submission.SolutionCode.Text, submission.Language )); } return(exerciseSlide.Exercise.CreateSubmission( submission.Id.ToString(), submission.SolutionCode.Text )); } return(new FileRunnerSubmission { Id = submission.Id.ToString(), Code = "// no slide anymore", Input = "", NeedRun = true }); }
public async Task ProcessResult(UserExerciseSubmission submission, RunningResults result) { if (result.StyleErrors == null || result.StyleErrors.Count == 0) { return; } if (result.Verdict != Verdict.Ok) { return; } var checking = submission.AutomaticChecking; if (!checking.IsRightAnswer) { return; } var exerciseSlide = (await courseManager.FindCourseAsync(submission.CourseId)) ?.FindSlideById(submission.SlideId, true) as ExerciseSlide; if (exerciseSlide == null) { return; } if (ulearnBotUserId == null) { ulearnBotUserId = await usersRepo.GetUlearnBotUserId(); } var exerciseMetricId = ExerciseController.GetExerciseMetricId(submission.CourseId, exerciseSlide); metricSender.SendCount($"exercise.{exerciseMetricId}.StyleViolation"); foreach (var error in result.StyleErrors) { await slideCheckingsRepo.AddExerciseCodeReview( submission.Id, ulearnBotUserId, error.Span.StartLinePosition.Line, error.Span.StartLinePosition.Character, error.Span.EndLinePosition.Line, error.Span.EndLinePosition.Character, error.Message ); var errorName = error.ErrorType; metricSender.SendCount("exercise.style_error"); metricSender.SendCount($"exercise.style_error.{errorName}"); metricSender.SendCount($"exercise.{exerciseMetricId}.style_error"); metricSender.SendCount($"exercise.{exerciseMetricId}.style_error.{errorName}"); } }
private async Task SendDeliveriesOfOneType(List <NotificationDelivery> deliveries) { if (deliveries.Count == 0) { return; } if (deliveries.Count == 1) { var delivery = deliveries[0]; var course = await courseManager.FindCourseAsync(delivery.Notification.CourseId); if (course == null) { log.Warn($"Can't find course {delivery.Notification.CourseId}"); await notificationsRepo.MarkDeliveryAsFailed(delivery); return; } try { await notificationSender.Send(delivery); await notificationsRepo.MarkDeliveryAsSent(delivery.Id); } catch (Exception e) { log.Warn(e, $"Can\'t send notification {delivery.NotificationId} to {delivery.NotificationTransport}. Will try later"); await notificationsRepo.MarkDeliveryAsFailed(delivery); } } else { try { await notificationSender.Send(deliveries); await notificationsRepo.MarkDeliveriesAsSent(deliveries.Select(d => d.Id).ToList()); } catch (Exception e) { log.Warn(e, $"Can\'t send multiple notifications [{string.Join(", ", deliveries.Select(d => d.NotificationId))}] to {deliveries[0].NotificationTransport}. Will try later"); await notificationsRepo.MarkDeliveriesAsFailed(deliveries); } } }
public async Task <bool> IsCourseVisibleForStudentsAsync(string courseId) { if (await courseManager.FindCourseAsync(courseId) == null) { return(false); } var visibleUnitsIds = await db.UnitAppearances .Where(u => u.CourseId == courseId) .Where(u => u.PublishTime <= DateTime.Now) .Select(u => u.UnitId) .ToListAsync(); var units = (await courseManager.GetCourseAsync(courseId)).GetUnitsNotSafe().Select(u => u.Id).ToHashSet(); units.IntersectWith(visibleUnitsIds); return(units.Any()); }
public async Task ProcessResult(UserExerciseSubmission submission, RunningResults result) { var ltiRequestJson = await ltiRequestsRepo.Find(submission.CourseId, submission.UserId, submission.SlideId); if (ltiRequestJson != null) { try { var exerciseSlide = (await courseManager.FindCourseAsync(submission.CourseId)).FindSlideById(submission.SlideId, true) as ExerciseSlide; var score = await visitsRepo.GetScore(submission.CourseId, submission.SlideId, submission.UserId); await LtiUtils.SubmitScore(exerciseSlide, submission.UserId, score, ltiRequestJson, ltiConsumersRepo); } catch (Exception e) { log.Error(e, "Мы не смогли отправить баллы на образовательную платформу"); } } }
public async Task BindModelAsync(ModelBindingContext bindingContext) { if (bindingContext == null) { throw new ArgumentNullException(nameof(bindingContext)); } // Specify a default argument name if none is set by ModelBinderAttribute var modelName = bindingContext.BinderModelName; if (string.IsNullOrEmpty(modelName)) { modelName = "courseId"; } // Try to fetch the value of the argument by name var valueProviderResult = bindingContext.ValueProvider.GetValue(modelName); if (valueProviderResult == ValueProviderResult.None) { return; } bindingContext.ModelState.SetModelValue(modelName, valueProviderResult); var value = valueProviderResult.FirstValue; // Check if the argument value is null or empty if (string.IsNullOrEmpty(value)) { return; } var model = await courseManager.FindCourseAsync(value); if (model == null) { bindingContext.ModelState.TryAddModelError(modelName, $"Course {value} not found"); } bindingContext.Result = model == null?ModelBindingResult.Failed() : ModelBindingResult.Success(model); }
public async Task ProcessResult(UserExerciseSubmission submission, RunningResults result) { if (result.StyleErrors == null || result.StyleErrors.Count == 0) { return; } if (result.Verdict != Verdict.Ok) { return; } var checking = submission.AutomaticChecking; if (!checking.IsRightAnswer) { return; } var exerciseSlide = (await courseManager.FindCourseAsync(submission.CourseId)) ?.FindSlideById(submission.SlideId, true) as ExerciseSlide; if (exerciseSlide == null) { return; } if (ulearnBotUserId == null) { ulearnBotUserId = await usersRepo.GetUlearnBotUserId(); } var exerciseMetricId = RunnerSetResultController.GetExerciseMetricId(submission.CourseId, exerciseSlide); await CreateStyleErrorsReviewsForSubmission(submission.Id, result.StyleErrors, exerciseMetricId); }
private async Task CreateDeliveriesForNotification(Notification notification) { var notificationType = notification.GetNotificationType(); log.Info($"Found new notification {notificationType} #{notification.Id}"); if (!notification.IsActual()) { log.Info($"Notification #{notification.Id}: is not actual more"); return; } var blockerNotifications = await notification.GetBlockerNotifications(serviceProvider); if (blockerNotifications.Count > 0) { log.Info( $"There are blocker notifications (this one will not be send if blocker notifications has been already sent to the same transport): " + $"{string.Join(", ", blockerNotifications.Select(n => $"{n.GetNotificationType()} #{n.Id}"))}" ); } Course course = null; if (!string.IsNullOrWhiteSpace(notification.CourseId)) { course = await courseManager.FindCourseAsync(notification.CourseId); if (course == null) { return; } } var recipientsIds = (await notification.GetRecipientsIdsAsync(serviceProvider, course)).ToHashSet(); recipientsIds = await FilterUsersWhoNotSeeCourse(notification, recipientsIds); log.Info($"Recipients list for notification {notification.Id}: {recipientsIds.Count} user(s)"); if (recipientsIds.Count == 0) { return; } var transportsSettings = db.NotificationTransportSettings .Include(s => s.NotificationTransport) .Where(s => s.CourseId == notification.CourseId && s.NotificationType == notificationType && !s.NotificationTransport.IsDeleted && recipientsIds.Contains(s.NotificationTransport.UserId)).ToList(); var commonTransports = db.NotificationTransports.Where(t => t.UserId == null && t.IsEnabled).ToList(); var isEnabledByDefault = notificationType.IsEnabledByDefault(); if (isEnabledByDefault) { log.Info($"Notification #{notification.Id}. This notification type is enabled by default, so collecting data for it"); var recipientsTransports = db.NotificationTransports.Where( t => recipientsIds.Contains(t.UserId) && !t.IsDeleted && t.IsEnabled ).ToList(); var notFoundTransports = recipientsTransports.Except(transportsSettings.Select(c => c.NotificationTransport), new NotificationTransportIdComparer()); foreach (var transport in notFoundTransports) { transportsSettings.Add(new NotificationTransportSettings { IsEnabled = true, NotificationTransport = transport, NotificationTransportId = transport.Id, }); } } else if (notification.IsNotificationForEveryone) { /* Add notification to all common transports */ /* It's used for notifications which should be sent to everyone in the course */ log.Info($"Notification #{notification.Id}. This notification type is sent to everyone, so add it to all common transports ({commonTransports.Count} transport(s)):"); foreach (var commonTransport in commonTransports) { log.Info($"Common transport {commonTransport}"); transportsSettings.Add(new NotificationTransportSettings { IsEnabled = true, NotificationTransport = commonTransport, NotificationTransportId = commonTransport.Id, }); } } var blockerNotificationsSentToTransports = new HashSet <int>( GetNotificationsDeliveries(blockerNotifications.Select(n => n.Id), transportsSettings.Select(s => s.NotificationTransportId)) .Select(d => d.NotificationTransportId) ); if (blockerNotificationsSentToTransports.Count > 0) { log.Info( "Blocked notifications have been already sent to follow transports:" + $"{string.Join(", ", blockerNotificationsSentToTransports)}" ); } var now = DateTime.Now; foreach (var transportSettings in transportsSettings) { log.Info($"Notification #{notification.Id}: add delivery to {transportSettings.NotificationTransport}, isEnabled: {transportSettings.IsEnabled}"); if (!transportSettings.IsEnabled) { continue; } if (!transportSettings.NotificationTransport.IsEnabled) { log.Info($"Transport {transportSettings.NotificationTransport} is fully disabled, ignore it"); continue; } /* Always ignore to send notification to user initiated this notification */ if (transportSettings.NotificationTransport.UserId == notification.InitiatedById) { log.Info($"Don't sent notification to the transport {transportSettings.NotificationTransport} because it has been initiated by this user"); continue; } if (blockerNotificationsSentToTransports.Contains(transportSettings.NotificationTransportId)) { log.Info($"Some blocker notification already has been sent to transport {transportSettings.NotificationTransport}, ignore it"); continue; } log.Info($"Notification #{notification.Id}: add delivery to {transportSettings.NotificationTransport}, sending at {now}"); db.NotificationDeliveries.Add(new NotificationDelivery { Notification = notification, NotificationTransportId = transportSettings.NotificationTransportId, CreateTime = now, NextTryTime = now, FailsCount = 0, Status = NotificationDeliveryStatus.NotSent, }); } }