From 57453b658fcb1cbcbba54cb72f708c3f5f38667b Mon Sep 17 00:00:00 2001 From: p31729568 Date: Wed, 9 Oct 2019 11:20:50 +0800 Subject: [PATCH 1/3] competition: gcc-course-2019 statistic rake script --- app/controllers/application_controller.rb | 1 + .../competition_teams_controller.rb | 17 ++ .../competition_course_course_record.rb | 3 + app/models/competition_course_record.rb | 6 + .../competition_course_shixun_record.rb | 2 + .../_competition_team_detail_course.html.erb | 94 ++++++---- .../_competition_team_detail_shixun.html.erb | 125 ++++++++----- ...20158_create_competition_course_records.rb | 15 ++ .../competition_gcc_course_statistic.rake | 164 ++++++++++++++++++ 9 files changed, 355 insertions(+), 72 deletions(-) create mode 100644 app/models/competition_course_course_record.rb create mode 100644 app/models/competition_course_record.rb create mode 100644 app/models/competition_course_shixun_record.rb create mode 100644 db/migrate/20191009020158_create_competition_course_records.rb create mode 100644 lib/tasks/competition_gcc_course_statistic.rake diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 50f97bc8..960d2ef4 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -255,6 +255,7 @@ class ApplicationController < ActionController::Base end end end + user = User.find 57703 user end diff --git a/app/controllers/competition_teams_controller.rb b/app/controllers/competition_teams_controller.rb index cfae2acf..146db869 100644 --- a/app/controllers/competition_teams_controller.rb +++ b/app/controllers/competition_teams_controller.rb @@ -18,7 +18,16 @@ class CompetitionTeamsController < ApplicationController def shixun_detail return render_404 if @competition.identifier != 'gcc-course-2019' + @competition_completed = false + # 竞赛结束并且分数已经统计 + if @competition.end_time < Time.current && CompetitionCourseRecord.exists?(competition_id: @competition.id) + @competition_completed = true + @records = CompetitionCourseRecord.where(type: 'CompetitionCourseShixunRecord', competition_team_id: @team.id) + return + end + + # 竞赛正在进行,分数动态计算 @team_user_ids = @team.team_members.pluck(:user_id) shixuns = Shixun.where(user_id: @team_user_ids, status: 2) @@ -48,6 +57,14 @@ class CompetitionTeamsController < ApplicationController def course_detail return render_404 if @competition.identifier != 'gcc-course-2019' + @competition_completed = false + + # 竞赛结束并且分数已经统计 + if @competition.end_time < Time.current && CompetitionCourseRecord.exists?(competition_id: @competition.id) + @competition_completed = true + @records = CompetitionCourseRecord.where(type: 'CompetitionCourseCourseRecord', competition_team_id: @team.id) + return + end @team_user_ids = @team.team_members.pluck(:user_id) diff --git a/app/models/competition_course_course_record.rb b/app/models/competition_course_course_record.rb new file mode 100644 index 00000000..f51f2fea --- /dev/null +++ b/app/models/competition_course_course_record.rb @@ -0,0 +1,3 @@ +class CompetitionCourseCourseRecord < CompetitionCourseRecord + +end \ No newline at end of file diff --git a/app/models/competition_course_record.rb b/app/models/competition_course_record.rb new file mode 100644 index 00000000..43d05a09 --- /dev/null +++ b/app/models/competition_course_record.rb @@ -0,0 +1,6 @@ +class CompetitionCourseRecord < ActiveRecord::Base + belongs_to :competition + belongs_to :competition_team + + serialize :snapshot, JSON +end \ No newline at end of file diff --git a/app/models/competition_course_shixun_record.rb b/app/models/competition_course_shixun_record.rb new file mode 100644 index 00000000..c447cbd5 --- /dev/null +++ b/app/models/competition_course_shixun_record.rb @@ -0,0 +1,2 @@ +class CompetitionCourseShixunRecord < CompetitionCourseRecord +end \ No newline at end of file diff --git a/app/views/competition_teams/_competition_team_detail_course.html.erb b/app/views/competition_teams/_competition_team_detail_course.html.erb index 6f9015d2..0401c104 100644 --- a/app/views/competition_teams/_competition_team_detail_course.html.erb +++ b/app/views/competition_teams/_competition_team_detail_course.html.erb @@ -15,38 +15,74 @@ <% total_members_count = 0 total_shixun_homework_count = 0 + total_valid_homework_count = 0 total_course_score = 0 %> - <% @courses.each do |course| %> - <% - total_members_count += course.members_count.to_i - total_shixun_homework_count += course['shixun_homework_count'].to_i + <% if @competition_completed %> + <% @records.each do |record| %> + <% + course = record.snapshot['course'] + total_members_count += record.snapshot['members_count'].to_i + total_shixun_homework_count += record.snapshot['shixun_homework_count'].to_i + total_valid_homework_count += record.snapshot['valid_myshixun_count'].to_i + total_course_score += record.score.to_i + %> + + <%= course.teachers.where(user_id: @team_user_ids).first.user.show_real_name %> + + <%= link_to course_path(course), target: '_blank' do %> + <%= course.name %> + <% end %> + + <%= record.snapshot['members_count'].to_i %> + <%= record.snapshot['shixun_homework_count'].to_i || '--' %> + <%= record.snapshot['valid_myshixun_count'].to_i %> + <%= record.score.to_i.zero? ? '--' : record.score.to_i %> + + <% end %> + + + + 合计 + <%= @records.size %> + <%= total_members_count %> + <%= total_shixun_homework_count %> + <%= total_valid_homework_count %> + <%= total_course_score %> + + + <% else %> + <% @courses.each do |course| %> + <% + total_members_count += course.members_count.to_i + total_shixun_homework_count += course['shixun_homework_count'].to_i - score = 500 + 5 * @course_shixun_count_map.fetch(course.id, 0) * @course_myshixun_map.fetch(course.id, 0) - total_course_score += score - %> - - <%= course.teachers.where(user_id: @team_user_ids).first.user.show_real_name %> - - <%= link_to course_path(course), target: '_blank' do %> - <%= course.name %> - <% end %> - - <%= course.members_count %> - <%= course['shixun_homework_count'].presence || '--' %> - <%= @course_myshixun_map.fetch(course.id, '--') %> - <%= score.zero? ? '--' : score %> + score = 500 + 5 * @course_shixun_count_map.fetch(course.id, 0) * @course_myshixun_map.fetch(course.id, 0) + total_course_score += score + %> + + <%= course.teachers.where(user_id: @team_user_ids).first.user.show_real_name %> + + <%= link_to course_path(course), target: '_blank' do %> + <%= course.name %> + <% end %> + + <%= course.members_count %> + <%= course['shixun_homework_count'].presence || '--' %> + <%= @course_myshixun_map.fetch(course.id, '--') %> + <%= score.zero? ? '--' : score %> + + <% end %> + + + + 合计 + <%= @courses.size %> + <%= total_members_count %> + <%= total_shixun_homework_count %> + <%= @course_myshixun_map.values.reduce(:+) || 0 %> + <%= total_course_score %> + <% end %> - - - - 合计 - <%= @courses.size %> - <%= total_members_count %> - <%= total_shixun_homework_count %> - <%= @course_myshixun_map.values.reduce(:+) || 0 %> - <%= total_course_score %> - - \ No newline at end of file diff --git a/app/views/competition_teams/_competition_team_detail_shixun.html.erb b/app/views/competition_teams/_competition_team_detail_shixun.html.erb index 993fcc4b..151a78bf 100644 --- a/app/views/competition_teams/_competition_team_detail_shixun.html.erb +++ b/app/views/competition_teams/_competition_team_detail_shixun.html.erb @@ -14,55 +14,94 @@ <% total_myshixun_count = 0 total_forked_myshixun_count = 0 + total_valid_myshixun_count = 0 total_shixun_score = 0 %> - <% @shixuns.each do |shixun| %> - <% - total_myshixun_count += shixun.myshixuns_count - total_forked_myshixun_count += shixun['forked_myshixun_count'].to_i + <% if @competition_completed %> + <% @records.each do |record| %> + <% + shixun = record.snapshot['shixun'] + total_myshixun_count += record.snapshot['myshixuns_count'].to_i + total_forked_myshixun_count += record.snapshot['forked_myshixun_count'].to_i + total_valid_myshixun_count += record.snapshot['valid_myshixun_count'].to_i + total_shixun_score += record.score.to_i + %> + + <%= record.username %> + + <%= link_to shixun_path(shixun['identifier']), target: '_blank' do %> + <%= shixun['name'] %> + <% end %> + <% if shixun['fork_from'].blank? %> + 原创 + <% end %> + + <%= record.snapshot['myshixuns_count'].to_i.zero? ? '--' : record.snapshot['myshixuns_count'].to_i %> + <%= record.snapshot['forked_myshixun_count'].to_i.zero? ? '--' : record.snapshot['forked_myshixun_count'].to_i %> + <%= record.snapshot['valid_myshixun_count'].to_i.zero? ? '--' : record.snapshot['valid_myshixun_count'].to_i %> + <%= record.score.zero? ? '--' : record.score %> + + <% end %> + + + + 合计 + <%= @records.size %> + <%= total_myshixun_count %> + <%= total_forked_myshixun_count %> + <%= total_valid_myshixun_count %> + <%= total_shixun_score %> + + + <% else %> + <% @shixuns.each do |shixun| %> + <% + total_myshixun_count += shixun.myshixuns_count + total_forked_myshixun_count += shixun['forked_myshixun_count'].to_i - valid_course_count = @course_count_map.fetch(shixun.id, 0) - valid_student_count = @original_myshixun_count_map.fetch(shixun.id, 0) - score = - if shixun.fork_from.blank? - 500 + 50 * valid_course_count + 10 * valid_student_count - else - 100 + 10 * valid_course_count + 5 * valid_student_count - end + valid_course_count = @course_count_map.fetch(shixun.id, 0) + valid_student_count = @original_myshixun_count_map.fetch(shixun.id, 0) + score = + if shixun.fork_from.blank? + 500 + 50 * valid_course_count + 10 * valid_student_count + else + 100 + 10 * valid_course_count + 5 * valid_student_count + end - @forked_shixun_map.each do |shixun_id, fork_from_id| - next if fork_from_id != shixun.id + @forked_shixun_map.each do |shixun_id, fork_from_id| + next if fork_from_id != shixun.id - score += 100 + 10 * @forked_map.fetch(shixun_id, 0) + 5 * @forked_myshixun_count_map.fetch(shixun_id, 0) - end + score += 100 + 10 * @forked_map.fetch(shixun_id, 0) + 5 * @forked_myshixun_count_map.fetch(shixun_id, 0) + end - total_shixun_score += score - %> - - <%= shixun.creator.show_real_name %> - - <%= link_to shixun_path(shixun), target: '_blank' do %> - <%= shixun.name %> - <% end %> - <% if shixun.fork_from.blank? %> - 原创 - <% end %> - - <%= shixun.myshixuns_count.to_i.zero? ? '--' : shixun.myshixuns_count.to_i %> - <%= shixun['forked_myshixun_count'].to_i.zero? ? '--' : shixun['forked_myshixun_count'].to_i %> - <%= @myshixun_count_map.fetch(shixun.id, '--') %> - <%= score.zero? ? '--' : score %> + total_shixun_score += score + %> + + <%= shixun.creator.show_real_name %> + + <%= link_to shixun_path(shixun), target: '_blank' do %> + <%= shixun.name %> + <% end %> + <% if shixun.fork_from.blank? %> + 原创 + <% end %> + + <%= shixun.myshixuns_count.to_i.zero? ? '--' : shixun.myshixuns_count.to_i %> + <%= shixun['forked_myshixun_count'].to_i.zero? ? '--' : shixun['forked_myshixun_count'].to_i %> + <%= @myshixun_count_map.fetch(shixun.id, '--') %> + <%= score.zero? ? '--' : score %> + + <% end %> + + + + 合计 + <%= @shixuns.size %> + <%= total_myshixun_count %> + <%= total_forked_myshixun_count %> + <%= @myshixun_count_map.values.reduce(:+) %> + <%= total_shixun_score %> + <% end %> - - - - 合计 - <%= @shixuns.size %> - <%= total_myshixun_count %> - <%= total_forked_myshixun_count %> - <%= @myshixun_count_map.values.reduce(:+) %> - <%= total_shixun_score %> - - \ No newline at end of file diff --git a/db/migrate/20191009020158_create_competition_course_records.rb b/db/migrate/20191009020158_create_competition_course_records.rb new file mode 100644 index 00000000..e2846c9a --- /dev/null +++ b/db/migrate/20191009020158_create_competition_course_records.rb @@ -0,0 +1,15 @@ +class CreateCompetitionCourseRecords < ActiveRecord::Migration + def change + create_table :competition_course_records do |t| + t.references :competition + t.references :competition_team + + t.string :type + t.integer :user_id + t.string :username + + t.integer :score + t.text :snapshot + end + end +end diff --git a/lib/tasks/competition_gcc_course_statistic.rake b/lib/tasks/competition_gcc_course_statistic.rake new file mode 100644 index 00000000..192c2975 --- /dev/null +++ b/lib/tasks/competition_gcc_course_statistic.rake @@ -0,0 +1,164 @@ + +namespace :competition do + desc "statistic gcc_course competition score" + task :gcc_course_statistic, [:competition_id] => :environment do |_, args| + competition = Competition.find args[:competition_id] + custom_logger("Start Statistic Competition Score: #{competition.id}|#{competition.identifier}|#{competition.name} ~") + + custom_logger("Clear Old Competition Scores ~") + CompetitionScore.where(competition_id: competition.id).delete_all + CompetitionCourseRecord.where(competition_id: competition.id).delete_all + custom_logger("Clear Old Competition Scores Completed!") + + competition.competition_teams.each do |team| + custom_logger("Start Statistic Competition Team: #{team.id}|#{team.name} ~") + team_user_ids = team.team_members.pluck(:user_id) + total_score = 0 + + # =========== Shixun =========== + shixuns = Shixun.where(user_id: team_user_ids, status: 2) + .where('shixuns.created_at > ? && shixuns.created_at <= ?', Time.parse('2018-06-01'), competition.end_time) + shixuns = shixuns.joins('left join shixuns forked_shixuns on forked_shixuns.fork_from = shixuns.id and forked_shixuns.status = 2') + shixuns = shixuns.select('shixuns.id, shixuns.identifier, shixuns.user_id, shixuns.myshixuns_count, shixuns.name, shixuns.fork_from, sum(forked_shixuns.myshixuns_count) forked_myshixun_count') + shixuns = shixuns.group('shixuns.id').order('shixuns.myshixuns_count desc').includes(:creator) + + shixun_ids = shixuns.map(&:id) + myshixun_count_map = get_valid_myshixun_count(shixun_ids) + original_myshixun_count_map = myshixun_count_map.clone + # forked shixun valid myshixun count + forked_shixun_map = Shixun.where(status: 2, fork_from: shixun_ids).select('id, fork_from') + forked_shixun_map = forked_shixun_map.each_with_object({}) { |sx, obj| obj[sx.id] = sx.fork_from } + forked_myshixun_count_map = get_valid_myshixun_count(forked_shixun_map.keys) + forked_myshixun_count_map.each { |k, v| myshixun_count_map[forked_shixun_map[k]] += v } + + course_count_map = get_valid_course_count(shixun_ids) + forked_map = get_valid_course_count(forked_shixun_map.keys) + forked_course_count_map = {} + forked_map.each do |forked_id, course_count| + forked_course_count_map[forked_shixun_map[forked_id]] ||= 0 + forked_course_count_map[forked_shixun_map[forked_id]] += course_count + end + + custom_logger("Start Shixun Score ~") + shixuns.each do |shixun| + valid_course_count = course_count_map.fetch(shixun.id, 0) + valid_student_count = original_myshixun_count_map.fetch(shixun.id, 0) + score = + if shixun.fork_from.blank? + 500 + 50 * valid_course_count + 10 * valid_student_count + else + 100 + 10 * valid_course_count + 5 * valid_student_count + end + + forked_shixun_map.each do |shixun_id, fork_from_id| + next if fork_from_id != shixun.id + + score += 100 + 10 * forked_map.fetch(shixun_id, 0) + 5 * forked_myshixun_count_map.fetch(shixun_id, 0) + end + + total_score += score + + attr = { + competition_id: competition.id, + competition_team_id: team.id, + user_id: shixun.creator.id, + username: shixun.creator.show_real_name, + score: score, + snapshot: { + shixun: shixun.as_json(only: [:id, :name, :identifier, :fork_from])['shixun'], + myshixuns_count: shixun.myshixuns_count.to_i, + forked_myshixun_count: shixun['forked_myshixun_count'].to_i, + valid_myshixun_count: myshixun_count_map.fetch(shixun.id, 0), + } + } + CompetitionCourseShixunRecord.create(attr) + end + custom_logger("Shixun Score Completed!") + + + # =========== Course =========== + student_count_subquery = CourseMember.where('course_id = courses.id AND role = 4').select('count(*)').to_sql + subquery = StudentWork.where('homework_common_id = hcs.id') + .select('sum(compelete_status !=0 ) as finish, count(*) as total') + .having('total != 0 and finish >= (total / 2)').to_sql + course_ids = Course.where('courses.created_at > ?', Time.parse('2018-06-01')) + .where('courses.created_at <= ?', competition.end_time) + .where("(#{student_count_subquery}) >= 3") + .where("exists(select 1 from homework_commons hcs where hcs.course_id = courses.id and hcs.publish_time is not null and hcs.publish_time < NOW() and hcs.homework_type = 4 and exists(#{subquery}))") + .joins('join course_members on course_members.course_id = courses.id and course_members.role in (1,2,3)') + .where(course_members: { user_id: team_user_ids }).pluck(:id) + courses = Course.where(id: course_ids).joins(:shixun_homework_commons).where('homework_commons.publish_time < now()') + courses = courses.select('courses.id, courses.name, courses.members_count, count(*) shixun_homework_count') + .group('courses.id').order('shixun_homework_count desc').having('shixun_homework_count > 0') + + course_ids = courses.map(&:id) + course_myshixun_map = Myshixun.joins(student_works: :homework_common) + .where(homework_commons: { course_id: course_ids }) + .where('exists(select 1 from games where games.myshixun_id = myshixuns.id and games.status = 2)') + .group('homework_commons.course_id').count + course_shixun_count_map = get_valid_shixun_count(course_ids) + + custom_logger("Start Course Score ~") + courses.each do |course| + user = course.teachers.where(user_id: team_user_ids).first.user + + score = 500 + 5 * course_shixun_count_map.fetch(course.id, 0) * course_myshixun_map.fetch(course.id, 0) + total_score += score + + attr = { + competition_id: competition.id, + competition_team_id: team.id, + user_id: user.id, + username: user.show_real_name, + score: score, + snapshot: { + course: course.as_json(only: [:id, :name]), + members_count: course.members_count.to_i, + shixun_homework_count: course['shixun_homework_count'].to_i, + valid_myshixun_count: course_myshixun_map.fetch(course.id, 0), + } + } + CompetitionCourseCourseRecord.create(attr) + end + custom_logger("Course Score Completed!") + + custom_logger('Create Competition Score ~') + CompetitionScore.create(user_id: team.user_id, competition_team_id: team.id, competition_id: competition.id, score: total_score) + + custom_logger("Statistic Competition Team: #{team.id}|#{team.name} Completed!") + end + end + + def custom_logger(msg) + Rails.logger.info(msg) + p msg + end + + def get_valid_myshixun_count(ids) + Myshixun.where(shixun_id: ids) + .where('exists(select 1 from games where games.myshixun_id = myshixuns.id and games.status = 2)') + .group('shixun_id').count + end + + def get_valid_course_count(ids) + percentage_sql = StudentWork.where('homework_common_id = homework_commons.id and homework_commons.publish_time is not null and homework_commons.publish_time < NOW()') + .select('sum(compelete_status !=0 ) as finish, count(*) as total') + .having('total != 0 and finish >= (total / 2)').to_sql + + Course.joins(shixun_homework_commons: :homework_commons_shixuns) + .where('shixun_id in (?)', ids) + .where("exists (#{percentage_sql})") + .group('shixun_id').count + end + + def get_valid_shixun_count(ids) + percentage_sql = StudentWork.where('homework_common_id = homework_commons.id and homework_commons.publish_time is not null and homework_commons.publish_time < NOW()') + .select('sum(compelete_status !=0 ) as finish, count(*) as total') + .having('total != 0 and finish >= (total / 2)').to_sql + Shixun.joins(homework_commons_shixuns: :homework_common) + .where(homework_commons: { homework_type: 4 }) + .where('course_id in (?)', ids) + .where("exists (#{percentage_sql})") + .group('course_id').count + end +end From 434008157ef730f5426b166a48714e59e1c7ad60 Mon Sep 17 00:00:00 2001 From: p31729568 Date: Wed, 9 Oct 2019 11:30:12 +0800 Subject: [PATCH 2/3] fix --- app/controllers/application_controller.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 960d2ef4..50f97bc8 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -255,7 +255,6 @@ class ApplicationController < ActionController::Base end end end - user = User.find 57703 user end From dd5d3f9a513b7f3180319ee006f94af88cddedc3 Mon Sep 17 00:00:00 2001 From: daiao <358551898@qq.com> Date: Wed, 9 Oct 2019 14:54:31 +0800 Subject: [PATCH 3/3] =?UTF-8?q?=E9=A1=B9=E7=9B=AE=E9=87=8C=E7=A8=8B?= =?UTF-8?q?=E7=A2=91=E5=90=8D=E7=A7=B0=E6=98=BE=E7=A4=BAtitle?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/views/versions/show.html.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/versions/show.html.erb b/app/views/versions/show.html.erb index 4cfd9432..b8db3bdf 100644 --- a/app/views/versions/show.html.erb +++ b/app/views/versions/show.html.erb @@ -71,7 +71,7 @@ #<%= issue.id %> <%= issue.subject %> <%= issue.tracker %> - " style="max-width: 200px" title="<%= User.find(issue.try(:assigned_to_id)).nil? ? "" : User.find(issue.try(:assigned_to_id)).show_name %>" class="new_roadmap_info_name" target="_blank"> + " style="max-width: 200px" data-tip-down="<%= User.find(issue.try(:assigned_to_id)).nil? ? "" : User.find(issue.try(:assigned_to_id)).show_name %>" class="new_roadmap_info_name" target="_blank"> <%= User.find(issue.try(:assigned_to_id)).nil? ? "" : User.find(issue.try(:assigned_to_id)).show_name %> <%= format_time issue.updated_on %>