namespace :competition do
desc " statistic gcc_course competition score "
task :extra_course_statistic , [ :end_time ] = > :environment do | _ , args |
end_time = Time . parse ( args [ :end_time ] )
start_time = Time . parse ( '2018-06-01' )
old_competition = Competition . find 9
competition = Competition . find 13
old_competition_user_ids = old_competition . team_members . pluck ( :user_id )
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
shixun_user_ids = Shixun . where . not ( user_id : old_competition_user_ids ) . where ( status : 2 ) . where ( 'shixuns.created_at > ? && shixuns.created_at <= ?' , start_time , end_time ) . pluck ( :user_id ) . uniq
course_user_ids = Course . where . not ( tea_id : old_competition_user_ids ) . where ( 'courses.created_at > ?' , start_time )
. where ( 'courses.created_at <= ?' , 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 < ? and hcs.homework_type = 4 and exists( #{ subquery } )) " , end_time )
. joins ( 'join course_members on course_members.course_id = courses.id and course_members.role in (1,2,3)' ) . pluck ( :tea_id )
user_ids = shixun_user_ids + course_user_ids
users = User . joins ( :user_extension ) . where ( id : user_ids ) . where ( user_extensions : { identity : 0 } )
competition . competition_teams . destroy_all
users . each do | user |
team = CompetitionTeam . create! ( competition_id : competition . id , user_id : user . id , name : user . real_name )
TeamMember . create! ( competition_team_id : team . id , user_id : user . id , role : 1 , competition_id : competition . id )
end
custom_logger ( " Start Statistic Competition Score ~ " )
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! " )
CompetitionTeam . where ( competition_id : competition . id ) . 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 <= ?' , start_time , 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 ( :user )
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 ] ] = myshixun_count_map [ forked_shixun_map [ k ] ] . to_i + v . to_i }
course_count_map = get_valid_course_count ( shixun_ids , end_time )
forked_map = get_valid_course_count ( forked_shixun_map . keys , end_time )
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 . user . id ,
username : shixun . user . show_real_name ,
score : score ,
type : 'CompetitionCourseShixunRecord' ,
snapshot : {
shixun : shixun . as_json ( only : [ :id , :name , :identifier , :fork_from ] ) ,
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 ) ,
}
}
CompetitionCourseRecord . 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 > ?' , start_time )
. where ( 'courses.created_at <= ?' , 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 < ? and hcs.homework_type = 4 and exists( #{ subquery } )) " , end_time )
. 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 ( :practice_homeworks ) . where ( 'homework_commons.publish_time < ?' , end_time )
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 , end_time )
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 ,
type : 'CompetitionCourseCourseRecord' ,
snapshot : {
course : course . as_json ( only : [ :id , :name ] ) ,
members_count : course . students . count . to_i ,
shixun_homework_count : course [ 'shixun_homework_count' ] . to_i ,
valid_myshixun_count : course_myshixun_map . fetch ( course . id , 0 ) ,
}
}
CompetitionCourseRecord . 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 , end_time )
percentage_sql = StudentWork . where ( 'homework_common_id = homework_commons.id and homework_commons.publish_time is not null and homework_commons.publish_time < ?' , end_time )
. select ( 'sum(compelete_status !=0 ) as finish, count(*) as total' )
. having ( 'total != 0 and finish >= (total / 2)' ) . to_sql
Course . joins ( practice_homeworks : :homework_commons_shixun )
. where ( 'shixun_id in (?)' , ids )
. where ( " exists ( #{ percentage_sql } ) " )
. group ( 'shixun_id' ) . count
end
def get_valid_shixun_count ( ids , end_time )
percentage_sql = StudentWork . where ( 'homework_common_id = homework_commons.id and homework_commons.publish_time is not null and homework_commons.publish_time < ?' , end_time )
. 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