Merge branch 'dev_aliyun' of http://bdgit.educoder.net/Hjqreturn/educoder into dev_aliyun

dev_forum
cxt 6 years ago
commit 4d8077723d

@ -39,6 +39,8 @@ gem 'pdfkit'
gem 'wkhtmltopdf-binary' gem 'wkhtmltopdf-binary'
#gem 'iconv' #gem 'iconv'
# markdown 转html
gem 'redcarpet', '~> 3.4'
gem 'rqrcode', '~> 0.10.1' gem 'rqrcode', '~> 0.10.1'
gem 'rqrcode_png' gem 'rqrcode_png'

@ -193,6 +193,7 @@ GEM
rb-inotify (0.9.10) rb-inotify (0.9.10)
ffi (>= 0.5.0, < 2) ffi (>= 0.5.0, < 2)
rchardet (1.8.0) rchardet (1.8.0)
redcarpet (3.4.0)
redis (4.1.0) redis (4.1.0)
redis-actionpack (5.0.2) redis-actionpack (5.0.2)
actionpack (>= 4.0, < 6) actionpack (>= 4.0, < 6)
@ -328,6 +329,7 @@ DEPENDENCIES
rails (~> 5.2.0) rails (~> 5.2.0)
rails-i18n (~> 5.1) rails-i18n (~> 5.1)
rchardet (~> 1.8) rchardet (~> 1.8)
redcarpet (~> 3.4)
redis-rails redis-rails
roo-xls roo-xls
rqrcode (~> 0.10.1) rqrcode (~> 0.10.1)

@ -427,6 +427,24 @@ class ApplicationController < ActionController::Base
container.to_json container.to_json
end end
# 实训中间层pod配置
def shixun_container_limit shixun
container = []
shixun.shixun_service_configs.each do |config|
mirror = config.mirror_repository
if mirror.name.present?
container << {:image => mirror.name,
:cpuLimit => config.cpu_limit,
:cpuRequest => config.lower_cpu_limit,
:memoryLimit => "#{config.memory_limit}M",
:memoryRequest => "#{config.request_limit}M",
:resourceLimit => "#{config.resource_limit}K",
:type => mirror.try(:main_type) == "1" ? "main" : "sub"}
end
end
container.to_json
end
# 毕设任务列表的赛选 # 毕设任务列表的赛选
def course_work(task, **option) def course_work(task, **option)
logger.info("#############{option}") logger.info("#############{option}")

@ -138,7 +138,7 @@ class ChallengesController < ApplicationController
# tab 0,nil 过关任务, 1 评测设置, 2 参考答案 # tab 0,nil 过关任务, 1 评测设置, 2 参考答案
def edit def edit
@tab = params[:tab].to_i @tab = params[:tab].to_i
@power = current_user.manager_of_shixun?(@shixun) && @shixun.status == 0 @power = @shixun.status == 0
challenge_num = Challenge.where(:shixun_id => @shixun).count challenge_num = Challenge.where(:shixun_id => @shixun).count
@position = @challenge.position @position = @challenge.position
@chooses = @challenge.challenge_chooses @chooses = @challenge.challenge_chooses
@ -151,17 +151,17 @@ class ChallengesController < ApplicationController
def index def index
uid_logger("identifier: #{params}") uid_logger("identifier: #{params}")
# 通过调试发现 这里includes(:games)性能会慢10倍 # 通过调试发现 这里includes(:games)性能会慢10倍
current_myshixun = @shixun.current_myshixun(current_user.id)
@challenges = @shixun.challenges.includes(:games).where("games.user_id" => (current_myshixun ? current_user.id : nil))
@challenges = @shixun.challenges.fields_for_list.includes(:games).where("games.user_id" => current_user.id) @editable = @shixun.status == 0 # before_action有判断权限如果没发布则肯定是管理人员
@editable = current_user.manager_of_shixun?(@shixun) && @shixun.status == 0
@user = current_user @user = current_user
end end
def show def show
@tab = params[:tab].nil? ? 1 : params[:tab].to_i @tab = params[:tab].nil? ? 1 : params[:tab].to_i
challenge_num = Challenge.where(shixun_id: @shixun).count challenge_num = @shixun.challenges_count
@power = current_user.manager_of_shixun?(@shixun) && @shixun.status == 0 @power = @shixun.status == 0 # 之前验证走过了是不是管理员,因此这里只用判断是否发布
@position = @challenge.position @position = @challenge.position
if @position < challenge_num if @position < challenge_num
@next_challenge = Challenge.where(:shixun_id => @shixun, :position => @position + 1).first @next_challenge = Challenge.where(:shixun_id => @shixun, :position => @position + 1).first
@ -279,9 +279,6 @@ class ChallengesController < ApplicationController
def find_shixun def find_shixun
@shixun = Shixun.find_by_identifier(params[:shixun_identifier]) @shixun = Shixun.find_by_identifier(params[:shixun_identifier])
if !current_user.shixun_permission(@shixun)
tip_exception(403, "..")
end
end end
# 通用接口 # 通用接口
@ -293,7 +290,7 @@ class ChallengesController < ApplicationController
def challenge_params def challenge_params
params.require(:challenge).permit(:subject, :task_pass, :difficulty, :score, :st, :modify_time, :test_set_average, params.require(:challenge).permit(:subject, :task_pass, :difficulty, :score, :st, :modify_time, :test_set_average,
:path, :exec_path, :show_type, :original_picture_path, :test_set_score, :path, :exec_path, :show_type, :original_picture_path, :test_set_score,
:expect_picture_path, :picture_path, :web_route, :answer) :expect_picture_path, :picture_path, :web_route, :answer, :exec_time)
end end
def chooce_params def chooce_params

@ -28,7 +28,6 @@ module GitCommon
end end
def file_content def file_content
logger.info("#################{@repo_path}, #{@path}")
@content = git_fle_content @repo_path, @path @content = git_fle_content @repo_path, @path
end end

@ -9,9 +9,10 @@ module GitHelper
# 版本库文件内容,带转码 # 版本库文件内容,带转码
def git_fle_content(repo_path, path) def git_fle_content(repo_path, path)
begin begin
logger.info("git file content: repo_path is #{repo_path}, path is #{path}")
content = GitService.file_content(repo_path: repo_path, path: path) content = GitService.file_content(repo_path: repo_path, path: path)
logger.info("@@@@@@@@@@@@@@@@@@#{content}") logger.info("git file content: content is #{content}")
decode_content = nil decode_content = nil
if content.present? if content.present?
content = content["content"] #6.24 -hs 这个为新增,因为当实训题里含有选择题时,这里会报错,undefined method `[]' for nil:NilClass content = content["content"] #6.24 -hs 这个为新增,因为当实训题里含有选择题时,这里会报错,undefined method `[]' for nil:NilClass
@ -31,7 +32,7 @@ module GitHelper
decode_content decode_content
rescue Exception => e rescue Exception => e
uid_logger_error(e.message) Rails.logger.error(e.message)
raise Educoder::TipException.new("文档内容获取异常") raise Educoder::TipException.new("文档内容获取异常")
end end
end end

@ -616,7 +616,7 @@ class ExerciseQuestionsController < ApplicationController
elsif params[:question_type].to_i == 2 && (params[:standard_answers].count > 1 || params[:question_choices].blank? || params[:question_choices].include?("")) #判断题的标准答案不能大于1个选项不能为空 elsif params[:question_type].to_i == 2 && (params[:standard_answers].count > 1 || params[:question_choices].blank? || params[:question_choices].include?("")) #判断题的标准答案不能大于1个选项不能为空
normal_status(-1,"判断题选项不能为空/标准答案不能大于1个") normal_status(-1,"判断题选项不能为空/标准答案不能大于1个")
elsif params[:question_type].to_i <= 1 && (params[:question_choices].blank? || params[:question_choices].include?("") || params[:question_choices].count < 2) #选择题选项不能为空,且不能小于2 elsif params[:question_type].to_i <= 1 && (params[:question_choices].blank? || params[:question_choices].include?("") || params[:question_choices].count < 2) #选择题选项不能为空,且不能小于2
normal_status(-1,"选择题选项内容不能为空,且不能少于3个!") normal_status(-1,"选择题选项内容不能为空,且不能少于2个!")
elsif params[:question_type].to_i == 3 && (params[:standard_answers].blank? || params[:standard_answers].count > 5 ) #填空题选项最多为5个,且如果为1个的话不允许修改is_ordered elsif params[:question_type].to_i == 3 && (params[:standard_answers].blank? || params[:standard_answers].count > 5 ) #填空题选项最多为5个,且如果为1个的话不允许修改is_ordered
normal_status(-1,"填空题标准答案不能为空/不能超过5个") normal_status(-1,"填空题标准答案不能为空/不能超过5个")
elsif params[:question_type].to_i == 4 && params[:standard_answers].count > 2 #简单题参考答案最多为1个 elsif params[:question_type].to_i == 4 && params[:standard_answers].count > 2 #简单题参考答案最多为1个
@ -640,7 +640,7 @@ class ExerciseQuestionsController < ApplicationController
if @exercise.exercise_status != 1 if @exercise.exercise_status != 1
question_score = @exercise_question.question_score #原来的分数 question_score = @exercise_question.question_score #原来的分数
update_question_score = params[:question_score].to_f.round(1) #传入的分数 update_question_score = params[:question_score].to_f.round(1) #传入的分数
choices_count = @exercise_question.exercise_choices.count #原来的选项个数 choices_count = @exercise_question.exercise_choices.size #原来的选项个数
exercise_choice_ids = @exercise_question.exercise_standard_answers.pluck(:exercise_choice_id).uniq exercise_choice_ids = @exercise_question.exercise_standard_answers.pluck(:exercise_choice_id).uniq
standard_answers_text = @exercise_question.exercise_standard_answers.pluck(:answer_text).uniq standard_answers_text = @exercise_question.exercise_standard_answers.pluck(:answer_text).uniq
update_choices_count = params[:question_choices].present? ? params[:question_choices].count : choices_count #传入的选项个数 update_choices_count = params[:question_choices].present? ? params[:question_choices].count : choices_count #传入的选项个数

@ -101,7 +101,7 @@ class ExercisesController < ApplicationController
@page = params[:page] || 1 @page = params[:page] || 1
@limit = params[:limit] || 15 @limit = params[:limit] || 15
@exercises = @exercises.page(@page).per(@limit) @exercises = @exercises.page(@page).per(@limit)
@exercises = @exercises.includes(:exercise_users,:exercise_questions,:exercise_group_settings) @exercises = @exercises&.includes(:exercise_users,:exercise_questions,:exercise_group_settings)
else else
@exercises = [] @exercises = []
end end
@ -188,7 +188,7 @@ class ExercisesController < ApplicationController
else else
@is_teacher_or = 0 #为学生 @is_teacher_or = 0 #为学生
end end
@exercise_questions = @exercise.exercise_questions.order("question_number ASC") @exercise_questions = @exercise.exercise_questions&.includes(:exercise_choices,:exercise_shixun_challenges,:exercise_standard_answers).order("question_number ASC")
rescue Exception => e rescue Exception => e
uid_logger_error(e.message) uid_logger_error(e.message)
tip_exception("试卷创建失败!") tip_exception("试卷创建失败!")
@ -1334,6 +1334,7 @@ class ExercisesController < ApplicationController
#导出空白试卷 #导出空白试卷
def export_exercise def export_exercise
@exercise_questions = @exercise.exercise_questions.includes(:exercise_choices).order("question_number ASC") @exercise_questions = @exercise.exercise_questions.includes(:exercise_choices).order("question_number ASC")
@request_url = request.base_url
filename = "#{current_user.real_name}_#{@course.name}_#{@exercise.exercise_name}_#{Time.current.strftime('%Y%m%d%H%M%S')}.pdf" filename = "#{current_user.real_name}_#{@course.name}_#{@exercise.exercise_name}_#{Time.current.strftime('%Y%m%d%H%M%S')}.pdf"
stylesheets = "#{Rails.root}/app/templates/exercise_export/exercise_export.css" stylesheets = "#{Rails.root}/app/templates/exercise_export/exercise_export.css"
render pdf: 'exercise_export/blank_exercise', filename: filename, stylesheets: stylesheets render pdf: 'exercise_export/blank_exercise', filename: filename, stylesheets: stylesheets
@ -1418,7 +1419,7 @@ class ExercisesController < ApplicationController
:best_counts => best_counts, :best_counts => best_counts,
} }
@exercise_questions = @exercise.exercise_questions @exercise_questions = @exercise.exercise_questions&.includes(:exercise_choices,:exercise_answers,:exercise_standard_answers,:exercise_shixun_challenges,:exercise_shixun_answers)
@paging_type = "percent" @paging_type = "percent"
# 按题型排序 # 按题型排序

@ -16,26 +16,27 @@ class FilesController < ApplicationController
sort = params[:sort] || 0 # 0: 降序1: 升序 sort = params[:sort] || 0 # 0: 降序1: 升序
sort_type = params[:sort_type] || 'created_on' # created_on时间排序 downloads下载次数排序; quotes: 引用次数排序 sort_type = params[:sort_type] || 'created_on' # created_on时间排序 downloads下载次数排序; quotes: 引用次数排序
course_second_category_id = params[:course_second_category_id] || 0 # 0: 为主目录, 其他为次目录id course_second_category_id = params[:course_second_category_id] || 0 # 0: 为主目录, 其他为次目录id
@user = current_user || nil @user = current_user
@attachments = @course.attachments.by_keywords(params[:search]) @attachments = @course.attachments.by_course_second_category_id(course_second_category_id)
.includes(attachment_group_settings: :course_group, author: [:user_extension, :course_members]) .includes(attachment_group_settings: :course_group, author: [:user_extension, :course_members])
.by_course_second_category_id(course_second_category_id)
.ordered(sort: sort.to_i, sort_type: sort_type.strip) .ordered(sort: sort.to_i, sort_type: sort_type.strip)
get_category(@course, course_second_category_id) get_category(@course, course_second_category_id)
@total_count = @attachments.size
@public_count = @attachments.publiced.size
@private_count = @total_count - @public_count
@attachments = @attachments.by_keywords(params[:search])
@attachments =
case @user.course_identity(@course) case @user.course_identity(@course)
when 5 when 5
# 课程学生 @attachments.published
@attachments = @attachments.published when 6, 7
when 6 || 7 @attachments.publiced.published
# 非课堂成员 else
@attachments = @attachments.publiced.published @attachments
end end
@total_count = @attachments.size
@public_count = @attachments.publiced.size
@private_count = @total_count - @public_count
@attachments = @attachments.page(@page).per(@page_size) @attachments = @attachments.page(@page).per(@page_size)
end end

@ -33,7 +33,7 @@ class GamesController < ApplicationController
is_teacher = @user.is_teacher? is_teacher = @user.is_teacher?
# 实训超时设置 # 实训超时设置
time_limit = @shixun.exec_time time_limit = game_challenge.exec_time
# 上一关、下一关 # 上一关、下一关
prev_game = @game.prev_of_current_game(@shixun.id, @game.myshixun_id, game_challenge.position) prev_game = @game.prev_of_current_game(@shixun.id, @game.myshixun_id, game_challenge.position)
@ -52,7 +52,7 @@ class GamesController < ApplicationController
record_onsume_time = EvaluateRecord.where(game_id: @game.id).first.try(:consume_time) record_onsume_time = EvaluateRecord.where(game_id: @game.id).first.try(:consume_time)
# myshixun_manager判断用户是否有权限查看隐藏测试集(TPM管理员平台认证的老师花费金币查看者) # myshixun_manager判断用户是否有权限查看隐藏测试集(TPM管理员平台认证的老师花费金币查看者)
myshixun_manager = @identity < USER::EDU_GAME_MANAGER myshixun_manager = @identity < User::EDU_GAME_MANAGER
# 选择题和编程题公共部分 # 选择题和编程题公共部分
@base_date = {st: @st, discusses_count: discusses_count, game_count: game_count, myshixun: @myshixun, @base_date = {st: @st, discusses_count: discusses_count, game_count: game_count, myshixun: @myshixun,
@ -66,7 +66,7 @@ class GamesController < ApplicationController
shixun_tomcat = edu_setting('cloud_bridge') shixun_tomcat = edu_setting('cloud_bridge')
service_host = edu_setting('vnc_url') service_host = edu_setting('vnc_url')
uri = "#{shixun_tomcat}/bridge/vnc/getvnc" uri = "#{shixun_tomcat}/bridge/vnc/getvnc"
params = {tpiID: @myshixun.id, :containers => "#{Base64.urlsafe_encode64(container_limit(@shixun.mirror_repositories))}"} params = {tpiID: @myshixun.id, :containers => "#{Base64.urlsafe_encode64(shixun_container_limit(@shixun))}"}
res = uri_post uri, params res = uri_post uri, params
if res && res['code'].to_i != 0 if res && res['code'].to_i != 0
raise("实训云平台繁忙繁忙等级99") raise("实训云平台繁忙繁忙等级99")
@ -426,12 +426,12 @@ class GamesController < ApplicationController
game_code = GameCode.where(:game_id => @game.try(:id), :path => path).first game_code = GameCode.where(:game_id => @game.try(:id), :path => path).first
if game_code.present? if game_code.present?
content = game_code.try(:new_code) content = game_code.try(:new_code)
@content = if @myshixun.mirror_name.select{|a| a.include?("MachineLearning") || a.include?("Python")}.present? && content.present? # @content = if @myshixun.mirror_name.select{|a| a.include?("MachineLearning") || a.include?("Python")}.present? && content.present?
content.gsub(/\t/, ' ') # content.gsub(/\t/, ' ')
else # else
content # content
end # end
update_file_content(@content, @myshixun.repo_path, path, current_user.mail, current_user.full_name, "game passed reset") update_file_content(content, @myshixun.repo_path, path, current_user.mail, current_user.full_name, "game passed reset")
else else
tip_exception("代码重置失败,代码为空") tip_exception("代码重置失败,代码为空")
end end
@ -461,6 +461,7 @@ class GamesController < ApplicationController
git_fle_content(@myshixun.shixun.repo_path, path) git_fle_content(@myshixun.shixun.repo_path, path)
rescue Exception => e rescue Exception => e
uid_logger_error("#{e.message}") uid_logger_error("#{e.message}")
# 如果已发布的TPM实训也不能获取到内容那么肯定是版本库异常了
if @myshixun.shixun.try(:status) < 2 if @myshixun.shixun.try(:status) < 2
tip_exception("代码获取异常,请检查实训模板的评测设置是否正确") tip_exception("代码获取异常,请检查实训模板的评测设置是否正确")
else else
@ -546,7 +547,7 @@ class GamesController < ApplicationController
br_params = {:tpiID => "#{@myshixun.id}", :tpiGitURL => "#{gitUrl}", :buildID => "#{@game.id}", br_params = {:tpiID => "#{@myshixun.id}", :tpiGitURL => "#{gitUrl}", :buildID => "#{@game.id}",
:instanceChallenge => "#{step}", :testCases => "#{testCases}", :resubmit => "#{resubmit}", :instanceChallenge => "#{step}", :testCases => "#{testCases}", :resubmit => "#{resubmit}",
:times => params[:first].to_i, :podType => @shixun.webssh, :content_modified => content_modified, :times => params[:first].to_i, :podType => @shixun.webssh, :content_modified => content_modified,
:containers => "#{Base64.urlsafe_encode64(container_limit(@shixun.mirror_repositories))}", :containers => "#{Base64.urlsafe_encode64(shixun_container_limit(@shixun))}",
:persistenceName => @shixun.identifier, :tpmScript => "#{tpmScript}", :persistenceName => @shixun.identifier, :tpmScript => "#{tpmScript}",
:timeLimit => "#{@shixun.exec_time}", :isPublished => (@shixun.status < 2 ? 0 : 1) } :timeLimit => "#{@shixun.exec_time}", :isPublished => (@shixun.status < 2 ? 0 : 1) }

@ -1285,7 +1285,7 @@ class HomeworkCommonsController < ApplicationController
# 代码查重届结果 # 代码查重届结果
def code_review_results def code_review_results
# 如果有未获取结果的查重操作 则先读取结果 # 如果有未获取结果的查重操作 则先读取结果
#get_new_code_reviews_result @homework get_new_code_reviews_result @homework
@current_user = current_user @current_user = current_user
# 列表数据 # 列表数据

@ -217,7 +217,7 @@ class MyshixunsController < ApplicationController
shixun_tomcat = edu_setting('tomcat_webssh') shixun_tomcat = edu_setting('tomcat_webssh')
uri = "#{shixun_tomcat}/bridge/webssh/getConnectInfo" uri = "#{shixun_tomcat}/bridge/webssh/getConnectInfo"
params = {tpiID:@myshixun.id, podType:@myshixun.shixun.try(:webssh), params = {tpiID:@myshixun.id, podType:@myshixun.shixun.try(:webssh),
containers:(Base64.urlsafe_encode64(container_limit @myshixun.shixun.mirror_repositories))} containers:(Base64.urlsafe_encode64(shixun_container_limit @myshixun.shixun))}
res = uri_post uri, params res = uri_post uri, params
if res && res['code'].to_i != 0 if res && res['code'].to_i != 0
tip_exception("实训云平台繁忙繁忙等级92") tip_exception("实训云平台繁忙繁忙等级92")
@ -243,43 +243,39 @@ class MyshixunsController < ApplicationController
# -----Repository # -----Repository
# TODO: 之类需要一个resubmit参数,但是是关于games. # TODO: 之类需要一个resubmit参数,但是是关于games.
def update_file def update_file
begin
@hide_code = Shixun.where(id: @myshixun.shixun_id).pluck(:hide_code).first @hide_code = Shixun.where(id: @myshixun.shixun_id).pluck(:hide_code).first
tip_exception("技术平台为空!") if @myshixun.mirror_name.blank? tip_exception("技术平台为空!") if @myshixun.mirror_name.blank?
path = params[:path].strip unless params[:path].blank? path = params[:path].strip unless params[:path].blank?
game_id = params[:game_id] game_id = params[:game_id]
game = Game.find(game_id) game = Game.find(game_id)
@content_modified = 0 @content_modified = 0
# params[:evaluate] 实训评测时更新必须给的参数,需要依据该参数做性能统计,其它类型的更新可以跳过 # params[:evaluate] 实训评测时更新必须给的参数,需要依据该参数做性能统计,其它类型的更新可以跳过
# 自动保存的时候evaluate为0点评测的时候为1 # 自动保存的时候evaluate为0点评测的时候为1
if params[:evaluate] == 1 if params[:evaluate] == 1
record = EvaluateRecord.create!(:user_id => current_user.id, :shixun_id => @myshixun.shixun_id, :game_id => game_id) @sec_key = generate_identifier(EvaluateRecord, 12)
uid_logger("-- game is #{game_id}, record id is #{record.id}, time is **** #{Time.now.strftime("%Y-%m-%d %H:%M:%S.%L")}") record = EvaluateRecord.create!(:user_id => current_user.id, :shixun_id => @myshixun.shixun_id, :game_id => game_id,
student_work_time = format("%.3f", (Time.now.to_f - record.created_at.to_f)).to_f :identifier => @sec_key)
record.update_attributes!(:student_work => student_work_time) uid_logger("-- game build: file update #{@sec_key}, record id is #{record.id}, time is **** #{Time.now.strftime("%Y-%m-%d %H:%M:%S.%L")}")
end end
unless @hide_code unless @hide_code
# 远程版本库文件内容 # 远程版本库文件内容
last_content = GitService.file_content(repo_path: @repo_path, path: path)["content"] last_content = GitService.file_content(repo_path: @repo_path, path: path)["content"]
content = params[:content]
content = if @myshixun.mirror_name.select{|a| a.include?("MachineLearning") || a.include?("Python")}.present? && params[:content].present?
params[:content].gsub(/\t/, ' ')
else
params[:content]
end
if content != last_content if content != last_content
@content_modified = 1 @content_modified = 1
author_name = current_user.full_name author_name = current_user.full_name
author_email = current_user.mail author_email = current_user.mail
message = params[:evaluate] == 0 ? "auto commit" : "task commit" message = params[:evaluate] == 0 ? "System automatically submitted" : "User submitted"
@content = GitService.update_file(repo_path: @repo_path, @content = GitService.update_file(repo_path: @repo_path,
file_path: path, file_path: path,
message: message, message: message,
content: content, content: content,
author_name: author_name, author_name: author_name,
author_email: author_email) author_email: author_email)
uid_logger("-- file update #{@content}")
end end
end end
@ -293,6 +289,10 @@ class MyshixunsController < ApplicationController
consume_time = format("%.3f", (Time.now.to_f - record.created_at.to_f)).to_f consume_time = format("%.3f", (Time.now.to_f - record.created_at.to_f)).to_f
record.update_attributes!(:file_update => consume_time) record.update_attributes!(:file_update => consume_time)
end end
rescue Exception => e
uid_logger_error(e.message)
tip_exception("文件内容更新异常,请稍后重试")
end
end end
# 渲染实训代码 # 渲染实训代码

@ -90,7 +90,7 @@ class PollsController < ApplicationController
@limit = params[:limit] || 15 @limit = params[:limit] || 15
@polls = @polls.page(@page).per(@limit) @polls = @polls.page(@page).per(@limit)
@polls = @polls.includes(:poll_users,:poll_questions,:poll_group_settings) @polls = @polls&.includes(:poll_users,:poll_questions,:poll_group_settings)
else else
@polls = [] @polls = []
@ -183,7 +183,7 @@ class PollsController < ApplicationController
else else
@is_teacher_or = 0 @is_teacher_or = 0
end end
@poll_questions = @poll.poll_questions.order("question_number ASC") @poll_questions = @poll.poll_questions&.includes(:poll_answers).order("question_number ASC")
rescue Exception => e rescue Exception => e
uid_logger_error(e.message) uid_logger_error(e.message)
tip_exception("没有权限") tip_exception("没有权限")
@ -1148,7 +1148,7 @@ class PollsController < ApplicationController
end end
def get_questions_count def get_questions_count
@poll_questions = @poll.poll_questions.order("question_number ASC") @poll_questions = @poll.poll_questions&.includes(:poll_answers,:poll_votes).order("question_number ASC")
@poll_questions_count = @poll_questions.count # 全部的题目数 @poll_questions_count = @poll_questions.count # 全部的题目数
@poll_question_singles = @poll_questions.ques_count(1).all.count # 单选题 @poll_question_singles = @poll_questions.ques_count(1).all.count # 单选题
@poll_question_doubles = @poll_questions.ques_count(2).all.count # 多选题 @poll_question_doubles = @poll_questions.ques_count(2).all.count # 多选题

@ -315,9 +315,13 @@ class ShixunsController < ApplicationController
# 镜像-实训关联表 # 镜像-实训关联表
ShixunMirrorRepository.create!(:shixun_id => @shixun.id, :mirror_repository_id => main_type.to_i) if main_type.present? ShixunMirrorRepository.create!(:shixun_id => @shixun.id, :mirror_repository_id => main_type.to_i) if main_type.present?
# 实训主镜像服务配置
ShixunServiceConfig.create!(:shixun_id => @shixun.id, :mirror_repository_id => main_type.to_i)
if sub_type.present? if sub_type.present?
sub_type.each do |mirror| sub_type.each do |mirror|
ShixunMirrorRepository.create!(:shixun_id => @shixun.id, :mirror_repository_id => mirror) ShixunMirrorRepository.create!(:shixun_id => @shixun.id, :mirror_repository_id => mirror)
# 实训子镜像服务配置
ShixunServiceConfig.create!(:shixun_id => @shixun.id, :mirror_repository_id => mirror)
end end
end end
@ -395,6 +399,18 @@ class ShixunsController < ApplicationController
use_scope = 0 use_scope = 0
end end
@shixun.update_attributes!(:use_scope => use_scope) @shixun.update_attributes!(:use_scope => use_scope)
# 超级管理员和运营人员才能保存 中间层服务器pod信息的配置
if current_user.admin? || current_user.business?
@shixun.shixun_service_configs.destroy_all
params[:mirror_id].each_with_index do |mirror_id, index|
ShixunServiceConfig.create!(:shixun_id => @shixun.id,
:cpu_limit => params[:cpu_limit][index],
:lower_cpu_limit => params[:lower_cpu_limit][index],
:memory_limit => params[:memory_limit][index],
:request_limit => params[:request_limit][index],
:mirror_repository_id => mirror_id)
end
end
rescue Exception => e rescue Exception => e
uid_logger_error(e.message) uid_logger_error(e.message)
tip_exception("实训保存失败") tip_exception("实训保存失败")
@ -553,11 +569,6 @@ class ShixunsController < ApplicationController
end end
end end
# REDO:开启实训时更新关联作品的状态
# TODO:这个可以异步。或者放到课程里面取,不要在开启实训这边做
# HomeworksService.new.update_myshixun_work_status myshixun
UpdateMyshixunWorkStatusJob.perform_later(myshixun.id)
@current_task = myshixun.current_task(myshixun.games) @current_task = myshixun.current_task(myshixun.games)
uid_logger("## shixun exec: myshixun id is #{myshixun.id}") uid_logger("## shixun exec: myshixun id is #{myshixun.id}")
rescue Exception => e rescue Exception => e

@ -17,7 +17,7 @@ class ZipsController < ApplicationController
end end
def export_exercises def export_exercises
exercises = ExportExercisesService.new(@exercise,@ex_users) exercises = ExportExercisesService.new(@exercise,@ex_users,@request_url)
file_name = filename_for_content_disposition(exercises.filename) file_name = filename_for_content_disposition(exercises.filename)
send_file exercises.ex_zip, filename: file_name, type: 'application/zip' send_file exercises.ex_zip, filename: file_name, type: 'application/zip'
@ -41,6 +41,7 @@ class ZipsController < ApplicationController
ActiveRecord::Base.transaction do ActiveRecord::Base.transaction do
begin begin
@exercise = Exercise.includes(:exercise_users,:exercise_questions).find_by(id:params[:exercise_id]) @exercise = Exercise.includes(:exercise_users,:exercise_questions).find_by(id:params[:exercise_id])
@request_url = request.base_url
group_id = params[:exercise_group_id] group_id = params[:exercise_group_id]
if @exercise.blank? if @exercise.blank?
normal_status(-1,"试卷不存在") normal_status(-1,"试卷不存在")
@ -48,19 +49,20 @@ class ZipsController < ApplicationController
@course = @exercise.course @course = @exercise.course
default_ex_users = @exercise.all_exercise_users(current_user.id).exercise_user_committed default_ex_users = @exercise.all_exercise_users(current_user.id).exercise_user_committed
default_ex_users_size = default_ex_users.size
@ex_users = default_ex_users #仅导出已提交的,截止后则是全部为提交的。 @ex_users = default_ex_users #仅导出已提交的,截止后则是全部为提交的。
#可以分班选择 #可以分班选择
if group_id.present? if group_id.present?
exercise_students = @course.students.course_find_by_ids("course_group_id",group_id) # 试卷所分班的全部人数 exercise_students = @course.students.where(course_group_id: group_id) # 试卷所分班的全部人数
user_ids = exercise_students.pluck(:user_id).reject(&:blank?) user_ids = exercise_students.pluck(:user_id).reject(&:blank?).uniq
@ex_users = @ex_users.exercise_commit_users(user_ids) @ex_users = @ex_users.where(user_id: user_ids)
end end
# @ex_users = @ex_users.first(200)
default_ex_users_size = @ex_users.size
if default_ex_users_size == 0 if default_ex_users_size == 0
normal_status(-1,"导出失败,暂时没有已提交的学生") normal_status(-1,"导出失败,暂时没有已提交的学生")
elsif default_ex_users_size > 200 elsif default_ex_users_size > 100
normal_status(-1,"导出数量超过200,请分班导出或联系网站管理员导出") normal_status(-1,"导出数量超过100,请分班导出或联系网站管理员导出")
end end
end end
rescue Exception => e rescue Exception => e

@ -1,6 +1,7 @@
# 所有的方法请按首字母的顺序依次列出 # 所有的方法请按首字母的顺序依次列出
module ApplicationHelper module ApplicationHelper
include Educoder::I18n include Educoder::I18n
include GitHelper
ONE_MINUTE = 60 * 1000 ONE_MINUTE = 60 * 1000
ONE_HOUR = 60 * ONE_MINUTE ONE_HOUR = 60 * ONE_MINUTE
@ -332,6 +333,23 @@ module ApplicationHelper
raw arr.join('') raw arr.join('')
end end
def to_markdown(text)
return nil if text.blank?
options = {
:autolink => true,
:no_intra_emphasis => true,
:fenced_code_blocks => true,
:lax_html_blocks => true,
:strikethrough => true,
:superscript => true,
:tables => true
}
markdown = Redcarpet::Markdown.new(Redcarpet::Render::HTML,options)
markdown.render(text).html_safe
end
end end

@ -1,5 +1,6 @@
module ExercisesHelper module ExercisesHelper
# include GitHelper
#获取每个学生对每个题的答案状态 #获取每个学生对每个题的答案状态
def get_each_student_exercise(exercise_id,exercise_questions,user_id) def get_each_student_exercise(exercise_id,exercise_questions,user_id)
@ -166,10 +167,13 @@ module ExercisesHelper
ex_score = ex&.question_score ex_score = ex&.question_score
full_scores = effictive_users.search_exercise_answer("score",ex_score).count #满分人数 full_scores = effictive_users.search_exercise_answer("score",ex_score).count #满分人数
no_full_scores = effictive_users.exercise_no_full_scores(ex_score).count #部分分数人数 no_full_scores = effictive_users.exercise_no_full_scores(ex_score).count #部分分数人数
all_zero_scores = effictive_users.search_exercise_answer("score",0.0).count #包含为0分的及未评阅的 zero_scores = effictive_users.search_exercise_answer("score",0.0).count #包含为0分的及未评阅的
review_scores = ex.exercise_answer_comments.count #主观题的评阅数量 # review_scores = ex.exercise_answer_comments.count #主观题的评阅数量
un_review_scores = effictive_users_count - review_scores #未评阅数 un_review_scores = effictive_users_count - full_scores - no_full_scores - zero_scores #未评阅数
zero_scores = all_zero_scores - un_review_scores #已评阅且答案未0分的人数 if un_review_scores < 0
un_review_scores = 0
end
# zero_scores = all_zero_scores - un_review_scores #已评阅且答案未0分的人数
main_scores_array = [full_scores,no_full_scores,zero_scores,un_review_scores] main_scores_array = [full_scores,no_full_scores,zero_scores,un_review_scores]
main_scores_array.each_with_index do |s,index| main_scores_array.each_with_index do |s,index|
if index == 0 if index == 0
@ -428,15 +432,19 @@ module ExercisesHelper
answer_status = 1 answer_status = 1
end end
ex_shixun_answer_content = answers_content&.where(exercise_shixun_challenge_id: exercise_cha.id) ex_shixun_answer_content = answers_content&.where(exercise_shixun_challenge_id: exercise_cha.id)
if ex_shixun_answer_content.blank? #把关卡的答案存入试卷的实训里 code = nil
if exercise_cha.challenge&.path.present?
cha_path = challenge_path(exercise_cha.challenge&.path) cha_path = challenge_path(exercise_cha.challenge&.path)
game_challenge = game.game_codes.search_challenge_path(cha_path)&.first game_challenge = game.game_codes.search_challenge_path(cha_path)&.first
if game_challenge.present? if game_challenge.present?
game_code = game_challenge game_code = game_challenge
code = game_code.try(:new_code) code = game_code.try(:new_code)
else else
code = git_fle_content(exercise_cha.shixun&.repo_path,cha_path) code = git_fle_content(game.myshixun.repo_path,cha_path)
end end
end
if ex_shixun_answer_content.blank? #把关卡的答案存入试卷的实训里
### Todo 实训题的_shixun_details里的代码是不是直接从这里取出就可以了涉及到code的多个版本库的修改
sx_option = { sx_option = {
:exercise_question_id => q.id, :exercise_question_id => q.id,
:exercise_shixun_challenge_id => exercise_cha.id, :exercise_shixun_challenge_id => exercise_cha.id,
@ -447,7 +455,7 @@ module ExercisesHelper
} }
ExerciseShixunAnswer.create(sx_option) ExerciseShixunAnswer.create(sx_option)
else else
ex_shixun_answer_content.first.update_column('score',exercise_cha_score) ex_shixun_answer_content.first.update_attributes(score:exercise_cha_score.round(1),answer_text:code)
end end
score5 += exercise_cha_score score5 += exercise_cha_score
else else
@ -637,7 +645,11 @@ module ExercisesHelper
end end
if student_status == 2 #当前为老师,或为学生且已提交 if student_status == 2 #当前为老师,或为学生且已提交
user_score_pre = exercise_answers.score_reviewed user_score_pre = exercise_answers.score_reviewed
user_score = user_score_pre.present? ? user_score_pre.pluck(:score).sum : nil if ques_type == 4 && user_score_pre.blank? #主观题时且没有大于0的分数时为空
user_score = nil
else
user_score = user_score_pre.present? ? user_score_pre.pluck(:score).sum : 0.0
end
end end
if user_score.present? && (user_score > q.question_score) if user_score.present? && (user_score > q.question_score)

@ -110,7 +110,7 @@ module PollsHelper
poll_user_name = user.nickname poll_user_name = user.nickname
end end
course_member = course_members.find_by(user_id:user.id) course_member = course_members.find_by(user_id:user.id)
course_group_id = course_members.present? ? course_member.course_group_id : nil course_group_id = course_member.present? ? course_member.course_group_id : nil
if course_group_id == 0 if course_group_id == 0
course_group_name = "未分班" course_group_name = "未分班"
else else

@ -20,7 +20,7 @@ class Challenge < ApplicationRecord
# acts_as_attachable # acts_as_attachable
scope :base_attrs, -> { select([:id, :subject, :position, :shixun_id, :st, :score, :path, :task_pass, :modify_time, scope :base_attrs, -> { select([:id, :subject, :position, :shixun_id, :st, :score, :path, :task_pass, :modify_time,
:web_route, :answer]) } :web_route, :answer, :exec_time]) }
scope :choose_type, -> { where(st: 1) } scope :choose_type, -> { where(st: 1) }
scope :practice_type, -> { where(st: 0) } scope :practice_type, -> { where(st: 0) }

@ -30,6 +30,8 @@ class Shixun < ApplicationRecord
has_one :shixun_info, dependent: :destroy has_one :shixun_info, dependent: :destroy
belongs_to :user belongs_to :user
# 实训服务配置
has_many :shixun_service_configs, :dependent => :destroy
scope :search_by_name, ->(keyword) { where("name like ? or description like ? ", scope :search_by_name, ->(keyword) { where("name like ? or description like ? ",

@ -0,0 +1,4 @@
class ShixunServiceConfig < ApplicationRecord
belongs_to :shixun
belongs_to :mirror_repository
end

@ -5,9 +5,10 @@ class ExerciseUserPdfService
attr_reader :exercise, :ex_user attr_reader :exercise, :ex_user
def initialize(exercise, ex_user) def initialize(exercise, ex_user,request_url)
@exercise = exercise @exercise = exercise
@ex_user = ex_user @ex_user = ex_user
@request_url = request_url
@ex_user_user = @ex_user.user @ex_user_user = @ex_user.user
@course = @exercise.course @course = @exercise.course
end end
@ -37,10 +38,10 @@ class ExerciseUserPdfService
kit = PDFKit.new(html) kit = PDFKit.new(html)
base_css = %w(app/templates/exercise_export/exercise_export.css) base_css = %w(app/templates/exercise_export/exercise_export.css)
base_css.each { |css| kit.stylesheets << Rails.root.join(css) } base_css.each { |css| kit.stylesheets << Rails.root.join(css) }
#-----正式需删掉 # #-----正式需删掉
# aa = File.open(Rails.root.join("public/123.html"),"w+") # aa = File.open(Rails.root.join("public/123.html"),"w+")
# aa.syswrite(kit.source) # aa.syswrite(kit.source)
#正式需删掉------- # #正式需删掉-------
file = Tempfile.new(filename) file = Tempfile.new(filename)
kit.to_pdf(file.path) kit.to_pdf(file.path)
file file

@ -3,9 +3,10 @@ class ExportExercisesService
include StudentWorksHelper include StudentWorksHelper
attr_reader :exercise, :ex_users attr_reader :exercise, :ex_users
def initialize(exercise, ex_users) def initialize(exercise, ex_users,request_url)
@exercise = exercise @exercise = exercise
@ex_users = ex_users @ex_users = ex_users
@request_url = request_url
end end
def filename def filename
@ -18,7 +19,7 @@ class ExportExercisesService
pdfs = [] pdfs = []
Zip::File.open(zip_file.path, Zip::File::CREATE) do |zip| Zip::File.open(zip_file.path, Zip::File::CREATE) do |zip|
ex_users.each do |ex_user| ex_users.each do |ex_user|
export = ExerciseUserPdfService.new(exercise, ex_user) export = ExerciseUserPdfService.new(exercise, ex_user,@request_url)
pdf = export.ex_pdf pdf = export.ex_pdf
pdfs << pdf pdfs << pdf
begin begin

@ -68,13 +68,17 @@
<span class="text-gray mlr5">(<%= q&.question_score %>分)</span> <span class="text-gray mlr5">(<%= q&.question_score %>分)</span>
</div> </div>
<div class="pbt5"> <div class="pbt5">
<% q_markdown = to_markdown(q.question_title) %>
<% q_title = q_markdown&.include?("src=\"") ? q_markdown&.gsub("src=\"","src=\"#{@request_url}")&.html_safe : q_markdown %>
<% if q.question_type == 5 %> <% if q.question_type == 5 %>
<span class="ques-title"><%= q.shixun_name.present? ? q.shixun_name&.html_safe : "" %></span> <% q_markdown_name = to_markdown(q.shixun_name) %>
<% q_name = q_markdown_name&.include?("src=\"") ? q_markdown_name&.gsub("src=\"","src=\"#{@request_url}")&.html_safe : q_markdown_name %>
<span class="ques-title" id="ques_marked_<%= index %>"><%= q_name %></span>
<div class="mt8 text-gray"> <div class="mt8 text-gray">
<span><%= q.question_title.present? ? q.question_title&.html_safe : "" %></span> <span id="ques_title_<%= index %>"><%= q_title %></span>
</div> </div>
<% else %> <% else %>
<span class="ques-title"><%= q.question_title.present? ? q.question_title&.html_safe : "" %></span> <span class="ques-title" id="ques_title_<%= index %>"><%= q_title %></span>
<% end %> <% end %>
</div> </div>
<div class="pbt5"> <div class="pbt5">
@ -132,4 +136,5 @@
</div> </div>
</div> </div>
</body> </body>
</html> </html>

@ -167,15 +167,15 @@
<% end %> <% end %>
</div> </div>
<div class="pbt5"> <div class="pbt5">
<% q_title = q.question_title&.html_safe %>
<% if q_type == 5 %> <% if q_type == 5 %>
<span class="ques-title"><%= q.shixun_name&.html_safe %></span> <% q_name = q.shixun_name&.html_safe %>
<span class="ques-title"><%= q_name&.include?("src=\"") ? q_name&.gsub("src=\"","src=\"#{@request_url}") : q_name %></span>
<div class="mt8 text-gray"> <div class="mt8 text-gray">
<span><%= q.question_title&.html_safe %></span> <span><%= q_title&.include?("src=\"") ? q_title&.gsub("src=\"","src=\"#{@request_url}") : q_title %></span>
</div> </div>
<% elsif q_type == 4 %>
<span class="ques-title"><%= q.question_title&.html_safe %></span>
<% else %> <% else %>
<span class="ques-title"><%= q.question_title&.html_safe %></span> <span class="ques-title"><%= q_title&.include?("src=\"") ? q_title&.gsub("src=\"","src=\"#{@request_url}") : q_title %></span>
<% end %> <% end %>
</div> </div>
</div> </div>

@ -7,7 +7,7 @@ json.chooses do
end end
if @tab == 0 if @tab == 0
# 本关任务tab的编辑模式 # 本关任务tab的编辑模式
json.(@challenge, :id, :subject, :task_pass, :difficulty, :score) json.(@challenge, :id, :subject, :task_pass, :difficulty, :score, :exec_time)
json.tags @challenge.challenge_tags.map(&:name) json.tags @challenge.challenge_tags.map(&:name)
elsif @tab == 1 elsif @tab == 1
# 评测设置的编辑模式 # 评测设置的编辑模式

@ -1,6 +1,10 @@
json.question_id question.id json.question_id question.id
# json.question_number question.question_number # json.question_number question.question_number
json.q_position ques_position.present? ? ques_position : question.question_number q_positon = question.question_number
if ques_position.present?
q_positon = ques_position
end
json.q_position q_positon
json.question_title question.question_title json.question_title question.question_title
json.question_type question.question_type json.question_type question.question_type
json.question_score question.question_score.round(1).to_s json.question_score question.question_score.round(1).to_s
@ -86,7 +90,7 @@ elsif question.question_type == 5
user_get_score = games_score[:s_score].present? ? games_score[:s_score] : 0.0 user_get_score = games_score[:s_score].present? ? games_score[:s_score] : 0.0
json.shixun_challenge_id s.id json.shixun_challenge_id s.id
if games_score[:games].count > 0 if games_score[:games].count > 0
json.partial! "exercises/shixun_details",games: games_score[:games], user_score: user_get_score,game_score: games_score[:game_score] json.partial! "exercises/shixun_details",games: games_score[:games], user_score: user_get_score,game_score: games_score[:game_score],shixun_challenge:s
else else
json.partial! "exercises/shixun_undo",games: [s], user_score: user_get_score ,game_score: s.question_score json.partial! "exercises/shixun_undo",games: [s], user_score: user_get_score ,game_score: s.question_score
end end

@ -26,6 +26,17 @@ json.shixun_detail do
json.position output.query_index json.position output.query_index
json.output_detail output_detail game, output json.output_detail output_detail game, output
end end
json.passed_code game.try(:lastest_code)
latest_code = nil
if shixun_challenge.challenge&.path.present?
if game.try(:lastest_code).blank?
cha_path = challenge_path(shixun_challenge.challenge&.path)
latest_code = git_fle_content(game.myshixun.repo_path,cha_path)
else
latest_code = game.try(:lastest_code)
end
end
json.passed_code latest_code
end end
end end

@ -1,3 +1,4 @@
json.content @content json.content @content
json.resubmit "#{@resubmit}" json.resubmit "#{@resubmit}"
json.sec_key "#{@sec_key}"
json.content_modified @hide_code ? false : @content_modified json.content_modified @hide_code ? false : @content_modified

@ -0,0 +1,5 @@
require 'rails_helper'
RSpec.describe ShixunServiceConfig, type: :model do
pending "add some examples to (or delete) #{__FILE__}"
end
Loading…
Cancel
Save