chromesetting
杨树林 5 years ago
commit a455692b1b

@ -1,410 +1,411 @@
class MyshixunsController < ApplicationController class MyshixunsController < ApplicationController
before_action :require_login, :check_auth, :except => [:training_task_status, :code_runinng_message] before_action :require_login, :check_auth, :except => [:training_task_status, :code_runinng_message]
before_action :find_myshixun, :except => [:training_task_status, :code_runinng_message] before_action :find_myshixun, :except => [:training_task_status, :code_runinng_message]
before_action :find_repo_name, :except => [:training_task_status, :code_runinng_message] before_action :find_repo_name, :except => [:training_task_status, :code_runinng_message]
skip_before_action :verify_authenticity_token, :only => [:html_content] skip_before_action :verify_authenticity_token, :only => [:html_content]
## TPI关卡列表 ## TPI关卡列表
def challenges def challenges
# @challenges = Challenge.where(shixun_id: params[:shixun_id]) # @challenges = Challenge.where(shixun_id: params[:shixun_id])
@shixun = @myshixun.shixun @shixun = @myshixun.shixun
@games = @myshixun.games.includes(:challenge).reorder("challenges.position") @games = @myshixun.games.includes(:challenge).reorder("challenges.position")
@identity = current_user.game_identity(@games.first) @identity = current_user.game_identity(@games.first)
end end
# For Admin # For Admin
# 强制重置实训 # 强制重置实训
# 前段需要按照操作过程提示 # 前段需要按照操作过程提示
def reset_my_game def reset_my_game
unless (current_user.admin? || current_user.id == @myshixun.user_id) unless (current_user.admin? || current_user.id == @myshixun.user_id)
tip_exception("403", "") tip_exception("403", "")
end end
begin begin
ActiveRecord::Base.transaction do ActiveRecord::Base.transaction do
begin begin
@shixun = Shixun.select(:id, :identifier, :challenges_count).find(@myshixun.shixun_id) @shixun = Shixun.select(:id, :identifier, :challenges_count).find(@myshixun.shixun_id)
@myshixun.destroy! @myshixun.destroy!
StudentWork.where(:myshixun_id => @myshixun.id).update_all(myshixun_id: 0, work_status: 0, work_score: nil, StudentWork.where(:myshixun_id => @myshixun.id).update_all(myshixun_id: 0, work_status: 0, work_score: nil,
final_score: nil, efficiency: 0, eff_score: 0, calculation_time: nil, cost_time: 0, compelete_status: 0) final_score: nil, efficiency: 0, eff_score: 0, calculation_time: nil, cost_time: 0, compelete_status: 0)
rescue Exception => e rescue Exception => e
logger.error("######reset_my_game_failed:#{e.message}") logger.error("######reset_my_game_failed:#{e.message}")
raise("ActiveRecord::RecordInvalid") raise("ActiveRecord::RecordInvalid")
end end
end end
# 删除版本库 # 删除版本库
GitService.delete_repository(repo_path: @repo_path) unless @shixun.is_choice_type? GitService.delete_repository(repo_path: @repo_path) unless @shixun.is_choice_type?
rescue Exception => e rescue Exception => e
if e.message != "ActiveRecord::RecordInvalid" if e.message != "ActiveRecord::RecordInvalid"
logger.error("######delete_repository_error-:#{e.message}") logger.error("######delete_repository_error-:#{e.message}")
end end
raise "delete_repository_error:#{e.message}" raise "delete_repository_error:#{e.message}"
end end
end end
# 代码运行中的信息接口 # 代码运行中的信息接口
# 这个方法是中间层主动调用的点击评测后中间层会发送参数过来告诉目前Pod的启动情况一次评测会调用两次请求 # 这个方法是中间层主动调用的点击评测后中间层会发送参数过来告诉目前Pod的启动情况一次评测会调用两次请求
def code_runinng_message def code_runinng_message
begin begin
jsonTestDetails = JSON.parse(params[:jsonTestDetails]) jsonTestDetails = JSON.parse(params[:jsonTestDetails])
game_id = jsonTestDetails['buildID'] game_id = jsonTestDetails['buildID']
message = jsonTestDetails['textMsg'] message = jsonTestDetails['textMsg']
if game_id.present? && message.present? if game_id.present? && message.present?
game = Game.find game_id game = Game.find game_id
msg = game.run_code_message msg = game.run_code_message
# 只有评测中的game才会创建和更新代码评测中的信息 # 只有评测中的game才会创建和更新代码评测中的信息
if game.status == 1 || game.status == 2 if game.status == 1 || game.status == 2
if msg.blank? if msg.blank?
RunCodeMessage.create!(:game_id => game_id, :status => 1, :message => message) RunCodeMessage.create!(:game_id => game_id, :status => 1, :message => message)
else else
msg.update_attributes(:status => (msg.status + 1), :message => message) msg.update_attributes(:status => (msg.status + 1), :message => message)
end end
end end
render :json => {:data => "success"} render :json => {:data => "success"}
end end
rescue Exception => e rescue Exception => e
render :json => {:data => "failed, exception_message: #{e}"} render :json => {:data => "failed, exception_message: #{e}"}
end end
end end
# 中间层评测接口 # 中间层评测接口
# taskId 即返回的game id # taskId 即返回的game id
# 返回结果params [:stauts] 0 表示成功,其它则失败 # 返回结果params [:stauts] 0 表示成功,其它则失败
# msg 错误信息 # msg 错误信息
# output 为测试用户编译输出结果 # output 为测试用户编译输出结果
# myshixun:status 1为完成实训 # myshixun:status 1为完成实训
# @jenkins: caseId对应test_set的positionpassed: 1表示成功0表示失败 # @jenkins: caseId对应test_set的positionpassed: 1表示成功0表示失败
# resubmit 1表示已通关后重新评测0表示非重新评测 # resubmit 1表示已通关后重新评测0表示非重新评测
# retry_status 0初始值1重新评测失败2重新评测成功 # retry_status 0初始值1重新评测失败2重新评测成功
# tpiRepoPath 中间层图片的workspace路径 # tpiRepoPath 中间层图片的workspace路径
# params[:jsonTestDetails] = '{"buildID":"19284","compileSuccess":"1", # params[:jsonTestDetails] = '{"buildID":"19284","compileSuccess":"1",
# "msg":[{"caseId":"1","expectedOutput":"MSAyIDMNCg","input":"MiAzIDE","output":"MSAyIDMNCg","passed":"1"}, # "msg":[{"caseId":"1","expectedOutput":"MSAyIDMNCg","input":"MiAzIDE","output":"MSAyIDMNCg","passed":"1"},
# {"caseId":"2","expectedOutput":"LTMgMSA2DQo","input":"LTMgNiAx","output":"LTMgMSA2DQo","passed":"1"}, # {"caseId":"2","expectedOutput":"LTMgMSA2DQo","input":"LTMgNiAx","output":"LTMgMSA2DQo","passed":"1"},
# {"caseId":"3","expectedOutput":"LTcgLTUgLTMNCg","input":"LTcgLTMgLTU","output":"LTcgLTUgLTMNCg","passed":"1"}], # {"caseId":"3","expectedOutput":"LTcgLTUgLTMNCg","input":"LTcgLTMgLTU","output":"LTcgLTUgLTMNCg","passed":"1"}],
# "outPut":"Y29tcGlsZSBzdWNjZXNzZnVsbHk","resubmit":"","status":"0"}' # "outPut":"Y29tcGlsZSBzdWNjZXNzZnVsbHk","resubmit":"","status":"0"}'
# params[:timeCost] = '{"evaluateEnd":"2017-11-24 11:04:37","pull":"0.086", # params[:timeCost] = '{"evaluateEnd":"2017-11-24 11:04:37","pull":"0.086",
# "createPod":"1.610","evaluateAllTime":2820,"evaluateStart":"2017-11-24 11:04:35","execute":"0.294"}' # "createPod":"1.610","evaluateAllTime":2820,"evaluateStart":"2017-11-24 11:04:35","execute":"0.294"}'
# params[:pics] = "a.png,b.png,c.png" # params[:pics] = "a.png,b.png,c.png"
def training_task_status def training_task_status
ActiveRecord::Base.transaction do ActiveRecord::Base.transaction do
begin begin
t1 = Time.now t1 = Time.now
uid_logger_dubug("@@@222222#{params[:jsonTestDetails]}") uid_logger_dubug("@@@222222#{params[:jsonTestDetails]}")
jsonTestDetails = JSON.parse(params[:jsonTestDetails]) jsonTestDetails = JSON.parse(params[:jsonTestDetails])
timeCost = JSON.parse(params[:timeCost]) timeCost = JSON.parse(params[:timeCost])
brige_end_time = Time.parse(timeCost['evaluateEnd']) if timeCost['evaluateEnd'].present? brige_end_time = Time.parse(timeCost['evaluateEnd']) if timeCost['evaluateEnd'].present?
return_back_time = format("%.3f", ( t1.to_f - brige_end_time.to_f)).to_f return_back_time = format("%.3f", ( t1.to_f - brige_end_time.to_f)).to_f
status = jsonTestDetails['status'] status = jsonTestDetails['status']
game_id = jsonTestDetails['buildID'] game_id = jsonTestDetails['buildID']
sec_key = jsonTestDetails['sec_key'] sec_key = jsonTestDetails['sec_key']
uid_logger_dubug("training_task_status start-#{game_id}-1#{Time.now.strftime("%Y-%m-%d %H:%M:%S.%L")}") uid_logger_dubug("training_task_status start-#{game_id}-1#{Time.now.strftime("%Y-%m-%d %H:%M:%S.%L")}")
resubmit = jsonTestDetails['resubmit'] resubmit = jsonTestDetails['resubmit']
outPut = tran_base64_decode64(jsonTestDetails['outPut']) outPut = tran_base64_decode64(jsonTestDetails['outPut'])
jenkins_testsets = jsonTestDetails['msg'] jenkins_testsets = jsonTestDetails['msg']
compile_success = jsonTestDetails['compileSuccess'] compile_success = jsonTestDetails['compileSuccess']
# message = Base64.decode64(params[:msg]) unless params[:msg].blank? # message = Base64.decode64(params[:msg]) unless params[:msg].blank?
game = Game.find(game_id) game = Game.find(game_id)
myshixun = game.myshixun myshixun = game.myshixun
challenge = game.challenge challenge = game.challenge
# test_sets = challenge.test_sets # test_sets = challenge.test_sets
if challenge.picture_path.present? if challenge.picture_path.present?
#pics = params[:files] #pics = params[:files]
pics = params[:tpiRepoPath] pics = params[:tpiRepoPath]
game.update_column(:picture_path, pics) game.update_column(:picture_path, pics)
end end
max_query_index = game.outputs ? (game.outputs.first.try(:query_index).to_i + 1) : 1 max_query_index = game.outputs ? (game.outputs.first.try(:query_index).to_i + 1) : 1
test_set_score = 0 test_set_score = 0
unless jenkins_testsets.blank? unless jenkins_testsets.blank?
jenkins_testsets.each_with_index do |j_test_set, i| jenkins_testsets.each_with_index do |j_test_set, i|
actual_output = tran_base64_decode64(j_test_set['output']) actual_output = tran_base64_decode64(j_test_set['output'])
#ts_time += j_test_set['testSetTime'].to_i #ts_time += j_test_set['testSetTime'].to_i
# is_public = test_sets.where(:position => j_test_set['caseId']).first.try(:is_public) # is_public = test_sets.where(:position => j_test_set['caseId']).first.try(:is_public)
ts_time = format("%.2f", j_test_set['testSetTime'].to_f/1000000000).to_f if j_test_set['testSetTime'] ts_time = format("%.2f", j_test_set['testSetTime'].to_f/1000000000).to_f if j_test_set['testSetTime']
ts_mem = format("%.2f", j_test_set['testSetMem'].to_f/1024/1024).to_f if j_test_set['testSetMem'] ts_mem = format("%.2f", j_test_set['testSetMem'].to_f/1024/1024).to_f if j_test_set['testSetMem']
Output.create!(:code => status, :game_id => game_id, :out_put => outPut, :test_set_position => j_test_set['caseId'], Output.create!(:code => status, :game_id => game_id, :out_put => outPut, :test_set_position => j_test_set['caseId'],
:actual_output => actual_output, :result => j_test_set['passed'].to_i, :query_index => max_query_index, :actual_output => actual_output, :result => j_test_set['passed'].to_i, :query_index => max_query_index,
:compile_success => compile_success.to_i, :sec_key => sec_key, :ts_time => ts_time, :ts_mem => ts_mem) :compile_success => compile_success.to_i, :sec_key => sec_key, :ts_time => ts_time, :ts_mem => ts_mem)
# 如果设置了按测试集给分,则需要统计测试集的分值 # 如果设置了按测试集给分,则需要统计测试集的分值
if challenge.test_set_score && j_test_set['passed'].to_i == 1 if challenge.test_set_score && j_test_set['passed'].to_i == 1
test_set_score += challenge.test_sets.where(:position => j_test_set['caseId']).pluck(:score).first test_set_score += challenge.test_sets.where(:position => j_test_set['caseId']).pluck(:score).first
end end
end end
end end
record = EvaluateRecord.where(:identifier => sec_key).first record = EvaluateRecord.where(:identifier => sec_key).first
answer_deduction_percentage = (100 - game.answer_deduction) / 100.to_f # 查看答案后剩余分数的百分比. answer_deduction_percentage = (100 - game.answer_deduction) / 100.to_f # 查看答案后剩余分数的百分比.
# answer_deduction是查看答案的扣分比例 # answer_deduction是查看答案的扣分比例
# status0表示评测成功 # status0表示评测成功
if status == "0" if status == "0"
if resubmit.present? if resubmit.present?
game.update_attributes!(:retry_status => 2, :resubmit_identifier => resubmit) game.update_attributes!(:retry_status => 2, :resubmit_identifier => resubmit)
challenge.path.split("").each do |path| challenge.path.split("").each do |path|
game_passed_code(path.try(:strip), myshixun, game_id) game_passed_code(path.try(:strip), myshixun, game_id)
end end
else else
game.update_attributes!(:status => 2, game.update_attributes!(:status => 2,
:end_time => Time.now, :end_time => Time.now,
:accuracy => format("%.4f", 1.0 / game.query_index)) :accuracy => format("%.4f", 1.0 / game.query_index))
myshixun.update_attributes!(:status => 1) if game.had_done == 1 myshixun.update_attributes!(:status => 1) if game.had_done == 1
challenge.path.split("").each do |path| challenge.path.split("").each do |path|
game_passed_code(path.try(:strip), myshixun, game_id) game_passed_code(path.try(:strip), myshixun, game_id)
end end
# 如果是已经发布的实训,则需要给出相应的奖励 # 如果是已经发布的实训,则需要给出相应的奖励
if challenge.shixun.try(:status) > 1 if challenge.shixun.try(:status) > 1
score = (challenge.score * answer_deduction_percentage).to_i score = (challenge.score * answer_deduction_percentage).to_i
if score > 0 if score > 0
reward_attrs = { container_id: game.id, container_type: 'Game', score: score } reward_attrs = { container_id: game.id, container_type: 'Game', score: score }
RewardGradeService.call(game.user, reward_attrs) RewardGradeService.call(game.user, reward_attrs)
RewardExperienceService.call(game.user, reward_attrs) RewardExperienceService.call(game.user, reward_attrs)
end end
# 需要扣除查看答案的分数 # 需要扣除查看答案的分数
game.update_attributes!(:final_score => score) game.update_attributes!(:final_score => score)
end end
# 更新实训关联的作品分数 TODO: 更新作品分数 # 更新实训关联的作品分数 TODO: 更新作品分数
# HomeworksService.new.update_myshixun_work_score myshixun # HomeworksService.new.update_myshixun_work_score myshixun
end end
# 如果过关了下一关的状态是3为开启则需要把状态改成1已开启 # 如果过关了下一关的状态是3为开启则需要把状态改成1已开启
# next_game = game.next_game # next_game = game.next_game
next_game = game.next_game(myshixun.shixun_id, game.myshixun_id, challenge.position) next_game = game.next_game(myshixun.shixun_id, game.myshixun_id, challenge.position)
next_game.update_column(:status, 0) if next_game.present? && next_game.status == 3 next_game.update_column(:status, 0) if next_game.present? && next_game.status == 3
# status == "-1" 表示返回结果错误 # status == "-1" 表示返回结果错误
else else
if resubmit.present? if resubmit.present?
game.update_attributes!(:retry_status => 1, :resubmit_identifier => resubmit) game.update_attributes!(:retry_status => 1, :resubmit_identifier => resubmit)
else else
# 评测没通关则,测试集对的个数给分,并且还要扣除用户是否查看答案的值 # 评测没通关则,测试集对的个数给分,并且还要扣除用户是否查看答案的值
test_set_percentage = test_set_score / 100.to_f # 测试集得分比 test_set_percentage = test_set_score / 100.to_f # 测试集得分比
score = (challenge.score * test_set_percentage * answer_deduction_percentage).to_i score = (challenge.score * test_set_percentage * answer_deduction_percentage).to_i
# 如果分数比上次多,则更新成绩 # 如果分数比上次多,则更新成绩
game_update = game_update =
if game.final_score < score if game.final_score < score
{final_score: score, status: 0} {final_score: score, status: 0}
else else
{status: 0} {status: 0}
end end
game.update_attributes!(game_update) game.update_attributes!(game_update)
end end
end end
test_cases_time = format("%.3f", (Time.now.to_f - t1.to_f)).to_f test_cases_time = format("%.3f", (Time.now.to_f - t1.to_f)).to_f
if record.present? if record.present?
consume_time = format("%.3f", (Time.now - record.created_at)).to_f consume_time = format("%.3f", (Time.now - record.created_at)).to_f
record.update_attributes!(:consume_time => consume_time, :git_pull => timeCost['pull'] , :create_pod => timeCost['createPod'], record.update_attributes!(:consume_time => consume_time, :git_pull => timeCost['pull'] , :create_pod => timeCost['createPod'],
:pod_execute => timeCost['execute'], :test_cases => test_cases_time, :pod_execute => timeCost['execute'], :test_cases => test_cases_time,
:brige => timeCost['evaluateAllTime'], :return_back => return_back_time) :brige => timeCost['evaluateAllTime'], :return_back => return_back_time)
end end
sucess_status sucess_status
# rescue Exception => e # rescue Exception => e
# tip_exception(e.message) # tip_exception(e.message)
# uid_logger_error("training_task_status error: #{e}") # uid_logger_error("training_task_status error: #{e}")
# raise ActiveRecord::Rollback # raise ActiveRecord::Rollback
end end
end end
end end
# 连接webssh # 连接webssh
def open_webssh def open_webssh
username = edu_setting('webssh_username') username = edu_setting('webssh_username')
password = edu_setting('webssh_password') password = edu_setting('webssh_password')
old_time = Time.now.to_i old_time = Time.now.to_i
begin begin
shixun_tomcat = edu_setting('tomcat_webssh') shixun_tomcat = edu_setting('tomcat_webssh')
uri = "#{shixun_tomcat}/bridge/webssh/getConnectInfo" uri = "#{shixun_tomcat}/bridge/webssh/getConnectInfo"
# 由于中间层采用混合云的方式因为local参数表示在有文件生成的实训是在本地生成还是在其他云端生成评测文件 # 由于中间层采用混合云的方式因为local参数表示在有文件生成的实训是在本地生成还是在其他云端生成评测文件
params = {tpiID:@myshixun.id, podType:@myshixun.shixun.try(:webssh), local: @myshixun.shixun.show_type != -1, local = @myshixun.shixun.challenges.where.not(show_type: -1).count == 0
containers:(Base64.urlsafe_encode64(shixun_container_limit @myshixun.shixun))} params = {tpiID:@myshixun.id, podType:@myshixun.shixun.try(:webssh), local: local,
res = uri_post uri, params containers:(Base64.urlsafe_encode64(shixun_container_limit @myshixun.shixun))}
if res && res['code'].to_i != 0 res = uri_post uri, params
tip_exception("实训云平台繁忙繁忙等级92") if res && res['code'].to_i != 0
end tip_exception("实训云平台繁忙繁忙等级92")
render :json => {:host => res['address'], end
:port => res['port'], render :json => {:host => res['address'],
:ws_url => res['ws_address'], :port => res['port'],
:username => username, :ws_url => res['ws_address'],
:password => password, :username => username,
:game_id => @myshixun.id, :password => password,
:webssh_url => "#{shixun_tomcat}/bridge"} :game_id => @myshixun.id,
rescue Exception => e :webssh_url => "#{shixun_tomcat}/bridge"}
logger.error(e) rescue Exception => e
render :json => {:error => e.try(:message)} logger.error(e)
ensure render :json => {:error => e.try(:message)}
use_time = Time.now.to_i - old_time ensure
logger.info "open_webssh tpiID #{@myshixun.id} use time #{use_time}" use_time = Time.now.to_i - old_time
end logger.info "open_webssh tpiID #{@myshixun.id} use time #{use_time}"
end end
end
include GitCommon
include GitCommon
# -----Repository
# TODO: 之类需要一个resubmit参数,但是是关于games. # -----Repository
def update_file # TODO: 之类需要一个resubmit参数,但是是关于games.
begin def update_file
@hide_code = Shixun.where(id: @myshixun.shixun_id).pluck(:hide_code).first begin
tip_exception("技术平台为空!") if @myshixun.mirror_name.blank? @hide_code = Shixun.where(id: @myshixun.shixun_id).pluck(:hide_code).first
path = params[:path].strip unless params[:path].blank? tip_exception("技术平台为空!") if @myshixun.mirror_name.blank?
game_id = params[:game_id] path = params[:path].strip unless params[:path].blank?
game = Game.find(game_id) game_id = params[:game_id]
@content_modified = 0 game = Game.find(game_id)
@content_modified = 0
# params[:evaluate] 实训评测时更新必须给的参数,需要依据该参数做性能统计,其它类型的更新可以跳过
# 自动保存的时候evaluate为0点评测的时候为1 # params[:evaluate] 实训评测时更新必须给的参数,需要依据该参数做性能统计,其它类型的更新可以跳过
if params[:evaluate] == 1 # 自动保存的时候evaluate为0点评测的时候为1
exec_time = game.challenge.try(:exec_time) if params[:evaluate] == 1
@sec_key = generate_identifier(EvaluateRecord, 12) exec_time = game.challenge.try(:exec_time)
record = EvaluateRecord.create!(:user_id => current_user.id, :shixun_id => @myshixun.shixun_id, :game_id => game_id, @sec_key = generate_identifier(EvaluateRecord, 12)
:identifier => @sec_key, :exec_time => exec_time) record = EvaluateRecord.create!(:user_id => current_user.id, :shixun_id => @myshixun.shixun_id, :game_id => game_id,
uid_logger_dubug("-- game build: file update #{@sec_key}, record id is #{record.id}, time is **** #{Time.now.strftime("%Y-%m-%d %H:%M:%S.%L")}") :identifier => @sec_key, :exec_time => exec_time)
end uid_logger_dubug("-- game build: file update #{@sec_key}, record id is #{record.id}, time is **** #{Time.now.strftime("%Y-%m-%d %H:%M:%S.%L")}")
# 隐藏代码文件 和 VNC的都不需要走版本库 end
unless @hide_code || (@myshixun.shixun&.vnc_evaluate && params[:evaluate].present?) # 隐藏代码文件 和 VNC的都不需要走版本库
# 远程版本库文件内容 unless @hide_code || (@myshixun.shixun&.vnc_evaluate && params[:evaluate].present?)
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 =
if python_file?(path) content =
params[:content].gsub(/\t/, ' ').gsub(/ /, ' ') if python_file?(path)
else params[:content].gsub(/\t/, ' ').gsub(/ /, ' ')
params[:content] else
end params[:content]
uid_logger_dubug("###11222333####{content}") end
uid_logger_dubug("###222333####{last_content}") uid_logger_dubug("###11222333####{content}")
uid_logger_dubug("###222333####{last_content}")
if content != last_content
@content_modified = 1 if content != last_content
@content_modified = 1
author_name = current_user.real_name
author_email = current_user.git_mail author_name = current_user.real_name
message = params[:evaluate] == 0 ? "System automatically submitted" : "User submitted" author_email = current_user.git_mail
uid_logger_dubug("112233#{author_name}") message = params[:evaluate] == 0 ? "System automatically submitted" : "User submitted"
uid_logger_dubug("112233#{author_email}") uid_logger_dubug("112233#{author_name}")
@content = GitService.update_file(repo_path: @repo_path, uid_logger_dubug("112233#{author_email}")
file_path: path, @content = GitService.update_file(repo_path: @repo_path,
message: message, file_path: path,
content: content, message: message,
author_name: author_name, content: content,
author_email: author_email) author_name: author_name,
end author_email: author_email)
end end
end
if game.status == 2
@resubmit = Time.now.to_i if game.status == 2
end @resubmit = Time.now.to_i
end
# 评测时间记录
if record.present? # 评测时间记录
consume_time = format("%.3f", (Time.now.to_f - record.created_at.to_f)).to_f if record.present?
record.update_attributes!(:file_update => consume_time) consume_time = format("%.3f", (Time.now.to_f - record.created_at.to_f)).to_f
end record.update_attributes!(:file_update => consume_time)
rescue Exception => e end
uid_logger_error(e.message) rescue Exception => e
tip_exception("文件内容更新异常,请稍后重试") uid_logger_error(e.message)
end tip_exception("文件内容更新异常,请稍后重试")
end end
end
# 渲染实训代码
# educodercss: 字符串以 分隔存储的是版本库css的路径 # 渲染实训代码
# educoderscript: 字符串以 分隔存储的是版本库js的路径 # educodercss: 字符串以 分隔存储的是版本库css的路径
# contents html实训的整体内容 # educoderscript: 字符串以 分隔存储的是版本库js的路径
def html_content # contents html实训的整体内容
@contents = params[:contents] || "" def html_content
edu_css = params[:educodercss] @contents = params[:contents] || ""
edu_js = params[:educoderscript] edu_css = params[:educodercss]
if @contents.present? edu_js = params[:educoderscript]
@contents = @contents.gsub("w3equalsign", "=").gsub("w3scrw3ipttag", "script").gsub("edulink", "link").html_safe if @contents.present?
end @contents = @contents.gsub("w3equalsign", "=").gsub("w3scrw3ipttag", "script").gsub("edulink", "link").html_safe
# css end
if edu_css.present? # css
css_path = edu_css.split(",") if edu_css.present?
css_path.each do |path| css_path = edu_css.split(",")
file_content = git_fle_content(@repo_path, path)["content"] css_path.each do |path|
file_content = tran_base64_decode64(file_content) unless file_content.blank? file_content = git_fle_content(@repo_path, path)["content"]
@contents = @contents.sub(/EDUCODERCSS/, "<style>#{file_content}</style>") file_content = tran_base64_decode64(file_content) unless file_content.blank?
end @contents = @contents.sub(/EDUCODERCSS/, "<style>#{file_content}</style>")
end end
# js end
if edu_js.present? # js
js_path = edu_js.split(",") if edu_js.present?
js_path.each do |path| js_path = edu_js.split(",")
file_content = git_fle_content(@repo_path, path)["content"] js_path.each do |path|
file_content = tran_base64_decode64(file_content) unless file_content.blank? file_content = git_fle_content(@repo_path, path)["content"]
@contents = @contents.sub(/EDUCODERJS/, "<script>#{file_content}</script>") file_content = tran_base64_decode64(file_content) unless file_content.blank?
end @contents = @contents.sub(/EDUCODERJS/, "<script>#{file_content}</script>")
end end
respond_to do |format| end
format.json respond_to do |format|
format.html{render :layout => false} format.json
end format.html{render :layout => false}
end end
end
# 最新可以用的并发测试接口
def sigle_mul_test # 最新可以用的并发测试接口
codes = %W(1 2 3 4 5 6 7 8 9 A B C D E F G H J K L N M O P Q R S T U V W X Y Z) def sigle_mul_test
begin codes = %W(1 2 3 4 5 6 7 8 9 A B C D E F G H J K L N M O P Q R S T U V W X Y Z)
identifiers = Myshixun.where(:shixun_id => params[:shixun_id].split(",")).pluck(:identifier) begin
ide = identifiers[rand(identifiers.length)] identifiers = Myshixun.where(:shixun_id => params[:shixun_id].split(",")).pluck(:identifier)
myshixun = Myshixun.where(:identifier => ide).first ide = identifiers[rand(identifiers.length)]
myshixun = Myshixun.where(:identifier => ide).first
game = myshixun.games.last
logger.warn("###2mul test game_build start ") game = myshixun.games.last
identifier = game.try(:identifier) logger.warn("###2mul test game_build start ")
if game.status == 2 identifier = game.try(:identifier)
code = codes.sample(8).join if game.status == 2
resubmit = "#{code}_#{myshixun.id}" code = codes.sample(8).join
end resubmit = "#{code}_#{myshixun.id}"
logger.warn("###3mul test game_build start ...") end
EvaluateRecord.create!(:user_id => myshixun.user_id, :shixun_id => myshixun.shixun.id, :game_id => game.id) logger.warn("###3mul test game_build start ...")
redirect_to "/api/games/#{identifier}/game_build?resubmit=#{resubmit}&content_modified=0&first=1" EvaluateRecord.create!(:user_id => myshixun.user_id, :shixun_id => myshixun.shixun.id, :game_id => game.id)
rescue Exception => e redirect_to "/api/games/#{identifier}/game_build?resubmit=#{resubmit}&content_modified=0&first=1"
logger.error("mul test failed ===> #{e.message}") rescue Exception => e
end logger.error("mul test failed ===> #{e.message}")
end end
end
def sync_code
shixun_tomcat = edu_setting('cloud_bridge') def sync_code
begin shixun_tomcat = edu_setting('cloud_bridge')
git_myshixun_url = repo_ip_url @myshixun.repo_path begin
git_shixun_url = repo_ip_url @myshixun.shixun.try(:repo_path) git_myshixun_url = repo_ip_url @myshixun.repo_path
git_myshixun_url = Base64.urlsafe_encode64(git_myshixun_url) git_shixun_url = repo_ip_url @myshixun.shixun.try(:repo_path)
git_shixun_url = Base64.urlsafe_encode64(git_shixun_url) git_myshixun_url = Base64.urlsafe_encode64(git_myshixun_url)
# todo: identifier 是以前的密码,用来验证的,新版如果不需要,和中间层协调更改. git_shixun_url = Base64.urlsafe_encode64(git_shixun_url)
params = {tpiID: "#{@myshixun.try(:id)}", tpiGitURL: "#{git_myshixun_url}", tpmGitURL: "#{git_shixun_url}", # todo: identifier 是以前的密码,用来验证的,新版如果不需要,和中间层协调更改.
identifier: "xinhu1ji2qu3"} params = {tpiID: "#{@myshixun.try(:id)}", tpiGitURL: "#{git_myshixun_url}", tpmGitURL: "#{git_shixun_url}",
uri = "#{shixun_tomcat}/bridge/game/resetTpmRepository" identifier: "xinhu1ji2qu3"}
res = uri_post uri, params uri = "#{shixun_tomcat}/bridge/game/resetTpmRepository"
if (res && res['code'] != 0) res = uri_post uri, params
tip_exception("实训云平台繁忙繁忙等级95") if (res && res['code'] != 0)
end tip_exception("实训云平台繁忙繁忙等级95")
shixun_new_commit = GitService.commits(repo_path: @myshixun.shixun.repo_path).first["id"] end
@myshixun.update_attributes!(commit_id: shixun_new_commit, reset_time: @myshixun.shixun.try(:reset_time)) shixun_new_commit = GitService.commits(repo_path: @myshixun.shixun.repo_path).first["id"]
# 更新完成后,弹框则隐藏不再提示 @myshixun.update_attributes!(commit_id: shixun_new_commit, reset_time: @myshixun.shixun.try(:reset_time))
@myshixun.update_column(:system_tip, false) # 更新完成后,弹框则隐藏不再提示
render_ok @myshixun.update_column(:system_tip, false)
rescue Exception => e render_ok
tip_exception("立即更新代码失败!#{e.message}") rescue Exception => e
end tip_exception("立即更新代码失败!#{e.message}")
end end
end
# -----End
# -----End
private
def find_myshixun private
@myshixun = Myshixun.find_by!(identifier: params[:identifier]) def find_myshixun
end @myshixun = Myshixun.find_by!(identifier: params[:identifier])
end
def find_repo_name
@repo_path = @myshixun.try(:repo_path) def find_repo_name
@path = params[:path] @repo_path = @myshixun.try(:repo_path)
end @path = params[:path]
end
def python_file?(path)
false if path.blank? def python_file?(path)
path.to_s.split(".").last.downcase == "py" false if path.blank?
end path.to_s.split(".").last.downcase == "py"
end end
end

@ -19,7 +19,8 @@ class NewShixunModel extends Component{
order:'desc', order:'desc',
diff:0, diff:0,
limit:15, limit:15,
sort:"myshixuns_count" sort:"myshixuns_count",
belongtoindex:0,
} }
} }
componentDidMount() { componentDidMount() {
@ -161,7 +162,17 @@ class NewShixunModel extends Component{
}) })
let{status,order,diff,limit,sort}=this.state; let{status,order,diff,limit,sort}=this.state;
if(this.props.type==='shixuns'){ if(this.props.type==='shixuns'){
this.getdatalist(1,value,status,undefined,order,diff,limit) this.getdatalist(1,value,status,undefined,order,diff,limit);
if(value==="all"){
this.setState({
belongtoindex:0
})
}else{
this.setState({
belongtoindex:1
})
}
}else{ }else{
this.getdatalist(1,value,undefined,undefined,order,undefined,limit,undefined,sort) this.getdatalist(1,value,undefined,undefined,order,undefined,limit,undefined,sort)
} }
@ -322,6 +333,7 @@ class NewShixunModel extends Component{
this.getdatalist(page,type,status,keyword,order,diff,limit) this.getdatalist(page,type,status,keyword,order,diff,limit)
} }
updatepathlist=(sorts,orders)=>{ updatepathlist=(sorts,orders)=>{
let{page,type,keyword,order,diff,limit,status,sort}=this.state; let{page,type,keyword,order,diff,limit,status,sort}=this.state;
let seartorders; let seartorders;
@ -352,7 +364,7 @@ class NewShixunModel extends Component{
} }
render() { render() {
let {diff,Grouplist,status,shixun_list,shixuns_count,page,type,order,sort}=this.state; let {diff,Grouplist,status,shixun_list,shixuns_count,page,type,order,sort,belongtoindex}=this.state;
// let {visible,patheditarry}=this.props; // let {visible,patheditarry}=this.props;
// console.log(Grouplist) // console.log(Grouplist)
// console.log(allGrouplist) // console.log(allGrouplist)
@ -446,7 +458,7 @@ class NewShixunModel extends Component{
<Spin spinning={this.state.isspinning}> <Spin spinning={this.state.isspinning}>
<div className={"clearfix educontent pr mb60shixun"}> <div className={"clearfix educontent pr mb60shixun"}>
<div className={"square-list clearfix"}> <div className={"square-list clearfix verticallayout"}>
<div className="newshixunheadersear"> <div className="newshixunheadersear">
<div style={{height:"53px"}}></div> <div style={{height:"53px"}}></div>
@ -472,7 +484,36 @@ class NewShixunModel extends Component{
onSearch={ (value)=>this.setdatafuns(value)} /> onSearch={ (value)=>this.setdatafuns(value)} />
</div> </div>
<div className="clearfix font-12 mt30">
{this.props.type==='shixuns'?
<div className="clearfix sortinxdirection mt30 intermediatecenterysls">
<p className="nandu">筛选</p>
<p className={belongtoindex===0?"clickbutstwo ml13":"clickbutstwos ml13"} onClick={()=>this.belongto("all")}>全部实训</p>
<p className={belongtoindex===1?"clickbutstwo ml20":"clickbutstwos ml20"} onClick={()=>this.belongto("mine")}>普通实训</p>
</div>:""
}
{/*{this.props.type==='shixuns'? <Dropdown overlay={menus}>*/}
{/* <a className="ant-dropdown-link color-grey-6">*/}
{/* {diff===0?"难度":diff===1?"初级":diff===2?"中级":diff===3?"高级":diff===4?"顶级":""}<Icon type="down" className={"color-grey-6"}/>*/}
{/* </a>*/}
{/*</Dropdown>:""}*/}
{this.props.type==='shixuns'?
<div className="clearfix sortinxdirection mt20 intermediatecenterysls">
<p className="nandu">难度</p>
<p className={diff===0?"clickbuts ml13":"clickbutst ml13"} onClick={()=>this.DropdownClick(0)}>全部</p>
<p className={diff===1?"clickbuts ml30":"clickbutst ml30"} onClick={()=>this.DropdownClick(1)}>初级</p>
<p className={diff===2?"clickbuts ml30":"clickbutst ml30"} onClick={()=>this.DropdownClick(2)}>中级</p>
<p className={diff===3?"clickbuts ml30":"clickbutst ml30"} onClick={()=>this.DropdownClick(3)}>高级</p>
<p className={diff===4?"clickbuts ml30":"clickbutst ml30"} onClick={()=>this.DropdownClick(4)}>顶级</p>
</div>:""
}
<div className={this.props.type==='shixuns'?"clearfix font-12 mt20":"clearfix font-12 mt30"}>
<div className="font-12 ml5 fl"> <div className="font-12 ml5 fl">
@ -509,17 +550,18 @@ class NewShixunModel extends Component{
</a> </a>
</Dropdown>:"":""} </Dropdown>:"":""}
{this.props.type==='shixuns'? <Dropdown overlay={menus}>
<a className="ant-dropdown-link color-grey-6">
{diff===0?"难度":diff===1?"初级":diff===2?"中级":diff===3?"高级":diff===4?"顶级":""}<Icon type="down" className={"color-grey-6"}/>
</a>
</Dropdown>:""}
</div> </div>
<div className="font-12 alltopiscright ml25 fr"> <div className="font-12 alltopiscright ml25 fl">
{/*<span className={"fr pointer color-grey-3"} onClick={()=>this.props.hideNewShixunModelType()}>返回</span>*/}
<span className={type==="mine"?"fr topcsactive pointer color-grey-3 color-blue":"fr pointer color-grey-3"} onClick={()=>this.belongto("mine")}>我的{this.props.type==='shixuns'?'实训':"课程"}</span> {this.props.type==='shixuns'?"":
<span className={type==="all"?"fr mr30 topcsactive pointer color-grey-3 color-blue":"fr mr30 pointer color-grey-3"} onClick={()=>this.belongto("all")}>全部{this.props.type==='shixuns'?'实训':"课程"}</span> <span className={type==="mine"?"fr topcsactive pointer color-grey-3 color-blue":"fr pointer color-grey-3"} onClick={()=>this.belongto("mine")}>我的课程</span>
}
{this.props.type==='shixuns'?"":
<span className={type==="all"?"fr mr30 topcsactive pointer color-grey-3 color-blue":"fr mr30 pointer color-grey-3"} onClick={()=>this.belongto("all")}>全部课程</span>
}
</div> </div>
</div> </div>

@ -407,3 +407,110 @@
align-items: center; align-items: center;
justify-content: center; justify-content: center;
} }
/* 中间居中 */
.intermediatecenter{
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
/* 简单居中 */
.intermediatecenterysls{
display: flex;
align-items: center;
}
.spacearound{
display: flex;
justify-content: space-around;
}
.spacebetween{
display: flex;
justify-content: space-between;
}
/* 头顶部居中 */
.topcenter{
display: -webkit-flex;
flex-direction: column;
align-items: center;
}
/* x轴正方向排序 */
/* 一 二 三 四 五 六 七 八 */
.sortinxdirection{
display: flex;
flex-direction:row;
}
/* x轴反方向排序 */
/* 八 七 六 五 四 三 二 一 */
.xaxisreverseorder{
display: flex;
flex-direction:row-reverse;
}
/* 垂直布局 正方向*/
/*
*/
.verticallayout{
display: flex;
flex-direction:column;
}
/* 垂直布局 反方向*/
.reversedirection{
display: flex;
flex-direction:column-reverse;
}
.nandu{
width: 42px;
height: 19px;
font-size: 14px;
color: #000000;
line-height: 19px;
margin-left: 6px;
}
.clickbuts{
text-align: center;
width: 60px;
height: 32px;
background: #4CACFF;
border-radius: 16px;
line-height: 30px;
color: #FFFFFF;
cursor:pointer;
}
.clickbutst{
height:19px;
font-size:14px;
color:#505050;
line-height:19px;
cursor:pointer;
}
.clickbutstwo{
text-align: center;
width: 85px;
height: 32px;
background: #4CACFF;
border-radius: 16px;
line-height: 30px;
color: #FFFFFF;
cursor:pointer;
}
.clickbutstwos{
height:19px;
font-size:14px;
color:#505050;
line-height:19px;
cursor:pointer;
}

Loading…
Cancel
Save