From d52ad1ef29ed94a7673efd8c22e4dd63e3af0f14 Mon Sep 17 00:00:00 2001 From: Just Me Date: Thu, 8 Feb 2024 19:21:46 +0200 Subject: [PATCH] Add API action for zeroing result for users without solutions --- app/channels/api_channel.rb | 49 ++++++++++++++++++++++++++++++------- 1 file changed, 40 insertions(+), 9 deletions(-) diff --git a/app/channels/api_channel.rb b/app/channels/api_channel.rb index 697eb78c..452e2e57 100644 --- a/app/channels/api_channel.rb +++ b/app/channels/api_channel.rb @@ -141,18 +141,34 @@ def zero_results data end end - def finish data + def zero_no_solution data return unless scoring_open data task = Task.find task_id + force_close_and_finish! task + dispatch_self 'notifications/push', kind: 'info', message: 'Zeroing results for users without solutions …' - task.update_column :scoring_open, false - RedisLockManager.release_all - dispatch_all 'locks/load', RedisLockManager.all - dispatch_all 'results/load', CriterionUserResult.includes(:user).where(criterion: task_criterions) - dispatch_all 'comments/load', Comment.includes(:user).where(task_id:) - dispatch_all 'app/finish' + users_without_any_solution = Set.new task_users.where.missing(:solutions).pluck(:id) + begin + ActiveRecord::Base.transaction do + task.contest.users.find_each do |user| + next if user.solutions.exists?(task_id:) + + task.criterions.each { CriterionUserResult.create_or_find_by!(user:, criterion: _1).update!(value: 0) } + comment = users_without_any_solution.include?(user.id) ? 'папка відсутня' : 'файл відсутній' + Comment.create_or_find_by!(user:, task_id:).update!(value: comment) + end + end + ensure + reopen! task + end + end + + def finish data + return unless scoring_open data + task = Task.find task_id + force_close_and_finish! task dispatch_self 'notifications/push', kind: 'info', message: 'Calculating results …' users_without_result = [] @@ -170,8 +186,7 @@ def finish data raise "Users that missing some result: #{users_without_result.to_sentence}" unless users_without_result.empty? end rescue StandardError => e - task.update_column :scoring_open, true - dispatch_self 'app/ready', ready_info + reopen! task raise e else dispatch_self 'notifications/push', kind: 'success', message: 'Results calculated' @@ -223,4 +238,20 @@ def scoring_open data dispatch_self 'errors/push', "#{data['action']} failed: Scoring is closed" false end + + def force_close_and_finish! task + task.update_column :scoring_open, false + RedisLockManager.release_all + dispatch_all 'locks/load', RedisLockManager.all + dispatch_all 'results/load', CriterionUserResult.includes(:user).where(criterion: task_criterions) + dispatch_all 'comments/load', Comment.includes(:user).where(task_id:) + dispatch_all 'app/finish' + end + + def reopen! task + task.update_column :scoring_open, true + dispatch_self 'results/load', CriterionUserResult.includes(:user).where(criterion: task_criterions) + dispatch_self 'comments/load', Comment.includes(:user).where(task_id:) + dispatch_self 'app/ready', ready_info + end end