class HackUserLastestCodesController < ApplicationController before_action :require_login, except: [:listen_result] before_action :find_user_hack, only: [:show, :code_debug, :update_code, :listen_result] before_action :update_user_hack_status, only: [:code_debug, :code_submit] before_action :require_auth_identity, only: [:update_code] before_action :require_manager_identity, only: [:update_code] def show;end def update_code @my_hack.update_attribute(:code, params[:code]) end # 调试代码 def code_debug exec_mode = "debug" error_status = 501 error_msg = "debug_error" oj_evaluate exec_mode, error_status, error_msg render_ok end # 提交 def code_submit exec_mode = "normal" error_status = 502 error_msg = "submit_error" oj_evaluate exec_mode, error_status, error_msg render_ok end # 提交结果显示 def result end # 接收中间件返回结果接口 # 调试模式: status: 0 表示评测无错误,其他 表示错误(如编译出错,执行出错,超时等) def listen_result logger.info("###########listen_result:#{params}") begin msg = JSON.parse(params[:msg]) # 只有编译出错时,才正则匹配错误行数 error_line= if params[:status] == "-4" regular_match_error_line params[:outPut], @my_hack.hack.language end # debug 与submit 公用的参数 ds_params = {input: msg['input'], output: msg['output'], hack_id: @hack.id, user_id: @my_hack.user_id, error_line: error_line, status: params[:status], error_msg: params[:outPut], execute_time: params[:executeTime], execute_memory: params[:executeMem]} ActiveRecord::Base.transaction do # debug模式与submit模式 if params[:execMode] == "debug" save_debug_data ds_params elsif params[:execMode] == "normal" save_submit_data ds_params end # 评测完成后,还原评测中的状态 @my_hack.update_attribute(:submit_status, 0) end rescue Exception => e logger.error("#########listen_result: #{e.message}") end end private def find_user_hack @my_hack = HackUserLastestCode.find_by(identifier: params[:identifier]) @hack = @my_hack.hack end def oj_evaluate exec_mode, error_status, error_msg request_url = "#{edu_setting('cloud_bridge')}/bridge/ojs/evaluate" testCases = Base64.urlsafe_encode64({input: params[:input]}.to_json) debug_params = {execMode: exec_mode, tpiID: @my_hack.identifier, testCases: testCases, platform: @my_hack.language, codeFileContent: @my_hack.code, timeLimit: @hack.time_limit, sec_key: Time.now.to_s} interface_post request_url, debug_params, error_status, error_msg # 每次评测提交数增加 @hack.increment!(:submit_num) end # 正则错误行数 def regular_match_error_line content, language case language when 'Java' content.scan(/.java.\d+/).map{|s| s.match(/\d+/)[0].to_i}.min when 'C', 'C++' content.scan(/\d:\d+: error/).map{|s| s.match(/\d+/)[0]}.min when 'Python' content.scan(/line \d+/).map{|s| s.match(/\d+/)[0].to_i}.min end end # 存储debug数据 def save_debug_data debug_params if @my_hack.hack_user_debug.present? @my_hack.hack_user_debug.update_attributes!(debug_params) else @my_hack.hack_user_debug.create!(debug_params) end end # 存储submit数据 def save_submit_data submit_params # 通关 if submit_params[:status] == "0" # 编程题已经发布,且之前未通关奖励积分 if @hack.status == 1 && !@my_hack.passed? reward_attrs = { container_id: game.id, container_type: 'Hack', score: @hack.score } RewardGradeService.call(@my_hack.user, reward_attrs) RewardExperienceService.call(@my_hack.user, reward_attrs) # 评测完成更新通过数 @hack.increment!(:pass_num) @my_hack.update_attribute(:passed, true) end end # 创建用户评测记录 @my_hack.hack_user_codes.create!(submit_params) end # 调试或提交改变状态 def update_user_hack_status @my_hack.update_attribute(:submit_status, 1) end # 只有自己才能改动代码 def require_identity if @my_hack.user_id != current_user.id tip_exception(403, "..") end end # 老师、自己、管理可以查看他人的编程题 def require_manager_identity unless current_user.certification_teacher? || admin_or_business? || @my_hack.user_id == current_user.id tip_exception(403, "..") end end # 只有自己才能评测 def require_auth_identity unless @my_hack.user_id == current_user.id tip_exception(403, "..") end end end