#coding=utf-8
class GamesController < ApplicationController
layout " base_myshixun "
skip_before_filter :verify_authenticity_token , :only = > [ :file_update ]
before_filter :find_myshixun , :only = > [ :index ]
before_filter :find_game , :only = > [ :show , :game_build , :entry , :next_step , :prev_step , :outputs_show , :file_edit , :file_update , :get_waiting_time , :web_display , :check_test_sets ,
:game_status , :change_status , :answer , :minus_score , :refresh_game_list , :reset_original_code , :reset_new_code , :evaluating_choice ,
:sync_codes , :myshixun_repair , :system_update , :enter_game , :get_repository_contents , :sync_modify_time , :challenges ]
before_filter :find_repository , :only = > [ :entry , :file_edit , :file_update , :reset_original_code , :reset_new_code , :html_show , :get_repository_contents ]
before_filter :allowd_manager , :except = > [ :show ]
# before_filter :allowd_view, :only => [:show]
before_filter :find__shixun_language , :only = > [ :entry ]
include ApplicationHelper
include GamesHelper
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 )
require 'open3'
# 同步更新最新代码
# 同步完成后, 需要更新myshixun的commit_id为实训的commit最新值
# --------------------------
# 新思路, 有冲突则则重置, 没有冲突直接pull
# identifier为password---
# --------------------------
def sync_codes
g = Gitlab . client
shixun_tomcat = Redmine :: Configuration [ 'shixun_tomcat' ]
begin
shixun_new_commit = g . commits ( @myshixun . shixun . try ( :gpid ) ) . first . try ( :id )
if @myshixun . commit_id != shixun_new_commit
if @myshixun . reset_time != @myshixun . shixun . try ( :reset_time )
flag = 2
else
flag = 0
end
else
flag = 1
end
git_myshixun_url = gitlab_url @myshixun
login = @myshixun . shixun . try ( :git_login )
# 如果educoder不是当前项目的成员, 则需要把educoder设置成管理员, 为了便于权限验证
# REDO: 如果用educoder的话, 可能其他成员也可以推代码
educoder_gid = Redmine :: Configuration [ 'educoder_gid' ]
Gitlab . client . add_team_member ( @myshixun . gpid , educoder_gid , 40 )
git_shixun_url = gitlab_url @myshixun . shixun
git_myshixun_url = Base64 . urlsafe_encode64 ( git_myshixun_url )
git_shixun_url = Base64 . urlsafe_encode64 ( git_shixun_url )
params = { tpiID : " #{ @myshixun . try ( :id ) } " , :tpiGitURL = > " #{ git_myshixun_url } " , :tpmGitURL = > " #{ git_shixun_url } " , :identifier = > " xinhu1ji2qu3 " }
uri = " #{ shixun_tomcat } /bridge/game/resetTpmRepository "
res = uri_exec uri , params
if ( res && res [ 'code' ] != 0 )
render :json = > { :status = > - 1 , :message = > " 实训云平台繁忙( 繁忙等级: 95) " }
return
end
shixun_new_commit = g . commits ( @myshixun . shixun . try ( :gpid ) ) . first . try ( :id )
Rails . logger . info ( " # # # # # # # Game -- myshixun " )
@myshixun . update_attributes! ( :commit_id = > shixun_new_commit , :reset_time = > @myshixun . shixun . try ( :reset_time ) )
if @game . challenge . st == 0 && @game . challenge . path . present?
paths = @game . challenge . path . split ( " ; " )
paths . each do | path |
game_code_init @game . id , path . try ( :strip )
end
end
render :json = > { :status = > 1 , :message = > " success " , :path = > @game . challenge . path }
rescue Exception = > e
@message = e . try ( :message )
logger . error ( e )
respond_to do | format |
format . js
end
end
end
def enter_game
if @game . status == 3
@game . update_attributes ( :status = > 0 , :open_time = > Time . now )
redirect_to myshixun_game_path ( @game , :myshixun_id = > @myshixun )
end
end
# 出现代码不存在、脚本异常等自动修复
# 88错误的修复等
def myshixun_repair
shixun_tomcat = Redmine :: Configuration [ 'shixun_tomcat' ]
begin
git_myshixun_url = gitlab_url @myshixun
git_myshixun_url = Base64 . urlsafe_encode64 ( git_myshixun_url )
params = { tpiID : " #{ @myshixun . try ( :id ) } " , :tpiGitURL = > " #{ git_myshixun_url } " , :tpmID = > " #{ @myshixun . shixun . try ( :id ) } " }
uri = " #{ shixun_tomcat } /bridge/game/solveProblems "
res = uri_exec uri , params
if ( res && res [ 'code' ] != 0 )
@message = " 实训云平台繁忙( 繁忙等级: 96) "
raise ( " 实训云平台繁忙( 繁忙等级: 96) " )
end
respond_to do | format |
format . js { redirect_to myshixun_game_path ( @game , :myshixun_id = > @myshixun ) }
end
rescue Exception = > e
@message = e . try ( :message )
logger . error ( e )
respond_to do | format |
format . js
end
end
end
def index
@games = @myshixun . games . includes ( :challenge )
@games_count = @games . count
respond_to do | format |
format . html
format . js
end
end
# mushixun的版本库必须创建时就创建
# 首次进入版本库自动打开文件
# path: "" && path: @game.path
# @praise 判断是否点赞
# @tread 判断是否踩
# git_repository_url @myshixun, "Myshixun"
# @st 0 实践任务 1 选择题任务
# begin表示用户从实训tpm列表点击进入
def show
# 该参数是为了判断是否需要加载loading
@is_subject = params [ :is_subject ]
redirect_to " /tasks/ #{ @game . identifier } "
return
# 验证版本库
gitUrl = gitlab_url @myshixun
gitUrl = Base64 . urlsafe_encode64 ( gitUrl )
shixun_tomcat = Redmine :: Configuration [ 'shixun_tomcat' ]
params = { :tpiID = > " #{ @myshixun . id } " , :tpiGitURL = > " #{ gitUrl } " }
# 监测版本库HEAD是否存在, 不存在则取最新的HEAD
uri = " #{ shixun_tomcat } /bridge/game/check "
res = uri_exec uri , params
if ( res && res [ 'code' ] != 0 )
logger . error ( " Verify the repository exception " )
end
# end
@is_subject = params [ :is_subject ]
# 防止页面ajax数据还没获取就关闭
@game . update_attribute ( :status , 0 ) if @game . status == 1
@game_challenge = @game . challenge
@position = @game_challenge . position
@challenges = Challenge . where ( :shixun_id = > @myshixun . shixun_id ) . includes ( :games ) . where ( " games.user_id = #{ @myshixun . user_id } " )
@shixun = @myshixun . shixun
# 判断tpm是否修改了
@tpm_modified = repository_is_modified ( @myshixun , @shixun . try ( :gpid ) )
unless ( @shixun . modify_time . blank? || @myshixun . modify_time . blank? || @shixun . reset_time . blank? || @myshixun . reset_time . blank? )
@tpm_script_modified = ( @shixun . reset_time > @myshixun . reset_time ? true : false )
end
if ( @game_challenge . modify_time . present? || @game . modify_time . present? )
@tpm_cases_modified = ( @game_challenge . modify_time != @game . modify_time ? true : false )
end
# end
@praise_count = PraiseTread . where ( :praise_tread_object_id = > @game_challenge . id , :praise_tread_object_type = > " Challenge " , :praise_or_tread = > 1 ) . count
@tread_count = PraiseTread . where ( :praise_tread_object_id = > @game_challenge . id , :praise_tread_object_type = > " Challenge " , :praise_or_tread = > 0 ) . count
# st: 判断是选择类型还是实训类型
@st = @game_challenge . st
@had_done = @game . had_done
@praise = PraiseTread . where ( " praise_tread_object_id=? and praise_tread_object_type=? and praise_or_tread=? and user_id=? " , @game_challenge . id , @game_challenge . class . to_s , 1 , User . current . id ) . first
@tread = PraiseTread . where ( " praise_tread_object_id=? and praise_tread_object_type=? and praise_or_tread=? and user_id=? " , @game_challenge . id , @game_challenge . class . to_s , 0 , User . current . id ) . first
@rev = @rev . nil? ? " master " : @rev
@type = @_params [ 'type' ]
challenge_path = @game_challenge . path
@discusses_count = @shixun . discusses . count
@arr_path = challenge_path . present? ? challenge_path . split ( " ; " ) : [ ]
# 默认打开文件
logger . info ( " repository id is #{ @repository . try ( :id ) } , repository's shixun_id = #{ @repository . try ( :myshixun_id ) } shixun_id = #{ @repository . try ( :shixun_id ) } , project_id => #{ @repository . try ( :project_id ) } " )
# 验证challenge文件名的合法性
# 获取文件content内容, 如果内容不存在则说明是目录, 否则则认为是文件
if ( @g . files ( @myshixun . gpid , @path , @rev ) . try ( :message ) . present? && ! @path . present? && @_params [ 'type' ] != " root " )
@path = @arr_path . reject ( & :blank? ) [ 0 ] . try ( :strip ) # 多文件(以'; '形式隔开),默认打开第一个文件
file_content = @g . files ( @myshixun . gpid , @path , @rev ) . content
if file_content . blank?
# gitlab缺陷: forked完成, 短暂时间内取不了内容的, 所以做一个小轮询, 间隔0.1秒
# 超过2秒则失败, 需通过页面刷新
for i in 0 .. 20 do
sleep ( 0 . 1 )
file_content = @g . files ( @myshixun . gpid , @path , @rev ) . content
unless file_content . blank?
logger . info ( " start: file_content is # # # #{ file_content . first ( 6 ) } " )
break
end
end
end
@content = tran_base64_decode64 ( file_content )
end
if @content . nil? || @_params [ 'type' ] == " root "
@entries = @repository . entries ( @path , @rev )
end
# 页面前后端分离数据转换
# test_sets = @game_challenge.test_sets
max_query_index = @game . outputs . first . try ( :query_index )
if max_query_index . present?
test_sets = TestSet . find_by_sql ( " SELECT o.actual_output, o.result, o.test_set_position, o.query_index,t.is_public,t.input, t.output, g.id as game_id, c.id as challenge_id FROM outputs o,games g ,challenges c,test_sets t where
g . id = #{@game.id} and o.query_index=#{max_query_index} and g.id = o.game_id and c.id= g.challenge_id and t.challenge_id = c.id and t.position =o.test_set_position order by o.query_index
" )
else
test_sets = TestSet . find_by_sql ( " SELECT t.is_public,t.input, t.output,t.position FROM games g ,challenges c,test_sets t where
g . id = #{@game.id} and c.id= g.challenge_id and t.challenge_id = c.id
" )
end
unless test_sets . blank?
@test_sets = test_set_static_data ( test_sets )
end
@test_sets_count = test_sets . count
@test_sets_hidden_count = test_sets . blank? ? 0 :test_sets . select { | test_set | test_set . is_public == false } . count
@test_sets_public_count = @test_sets_count - @test_sets_hidden_count
had_test = Output . where ( :game_id = > @game . id , :query_index = > ( @game . query_index - 1 ) )
@had_test_count = had_test . count
@had_passed_testsests_error_count = had_test . blank? ? 0 : had_test . select { | had_test | had_test . result == false } . count
@had_passed_testsests_error_count = @had_test_count - @had_passed_testsests_error_count
@had_passed_testsests_hidden_count = had_test . blank? ? 0 : had_test . select { | had_test | had_test . result == true && had_test . is_public == false } . count
@had_passed_testsests_public_count = had_test . blank? ? 0 : had_test . select { | had_test | had_test . result == true && had_test . is_public == true } . count
@mirror_name = @myshixun . mirror_name
@final_score = ( ( @shixun . status < = 1 ) ? 0 : @game . final_score . to_i )
if @myshixun . shixun . status < = 1 || ( @game . final_score != 0 && @game . answer_open > 0 )
@gold = 0
else
if @game . answer_open > 0 && @game . final_score == 0
@gold = - @game_challenge . score . to_i
else
@gold = @game . final_score . to_i
end
end
#@gold = @myshixun.shixun.status <= 1 ? 0 : ((@game.answer_open? && @game.final_score == 0 && @game.status == 2) ? -@game_challenge.score.to_i : @game.final_score.to_i)
@had_done = @game . had_done
@language = @game_challenge . shixun . language
@mirror_name = @myshixun . mirror_name
error_position = had_test . blank? ? nil : had_test . select { | had_test | had_test . result == false } . last
logger . info ( " latest output id is #{ error_position . id unless error_position . blank? } " )
@latest_output = error_position . try ( :out_put ) . gsub ( / \ n / , '<br/>' ) . gsub ( / \ t / , ' ' ) . to_json unless error_position . try ( :out_put ) . blank?
logger . info ( @latest_output )
@power = ( User . current . manager_of_shixun? ( @shixun ) || ( User . current . try ( :professional_certification ) && User . current . user_extensions . try ( :identity ) == 0 ) || @game . test_sets_view ) ? true : false
@record = EvaluateRecord . where ( :game_id = > @game . id ) . first . try ( :consume_time )
respond_to do | format |
format . html
format . js
end
rescue Exception = > e
logger . error ( " game error # # # # # # # # # # # # # #{ e . message } " )
flash [ :error ] = e . message
end
def get_repository_contents
@rev = @rev . nil? ? " master " : @rev
@path = params [ :path ] . try ( :strip ) # 多文件(以'; '形式隔开),默认打开第一个文件
file_content = @g . files ( @myshixun . gpid , @path , @rev ) . content
@content = tran_base64_decode64 ( file_content )
end
# 代码预览
def entry
# entry_and_raw(false)
@arr_path = @game . challenge . path . split ( " ; " )
file_content = @g . files ( @myshixun . gpid , @path , @rev ) . content
@content = tran_base64_decode64 ( file_content )
# @content = @repository.cat(@path, @rev)
end
def file_edit
# entry_and_raw(false)
# @content = @repository.cat(@path, @rev).strip
# # respond_to do |format|
# # format.js
# end
end
def sync_modify_time
@game . update_column ( :modify_time , @game . challenge . try ( :modify_time ) )
# return {:status => 1, :message => "success"}
render :json = > { :status = > 1 , :message = > " success " }
end
def file_update
# render :json => {:success => "success", :resubmit => '11111'}
logger . info ( " file_update start # 1** #{ @game . id } **** #{ Time . now . strftime ( " %Y-%m-%d %H:%M:%S.%L " ) } " )
ActiveRecord :: Base . transaction do
if params [ :evaluate ] . present?
# 创建评测记录
record = EvaluateRecord . create! ( :user_id = > User . current . id , :shixun_id = > @myshixun . shixun . id , :game_id = > @game . id )
logger . info ( " file_update start # 2** #{ @game . id } **** #{ Time . now . strftime ( " %Y-%m-%d %H:%M:%S.%L " ) } " )
# @myshixun.student_works.update_all(:update_time => Time.now) if !@myshixun.student_works.blank?
student_work_time = format ( " %.3f " , ( Time . now . to_f - record . created_at . to_f ) ) . to_f
record . update_attributes! ( :student_work = > student_work_time )
end
logger . info ( " file_update start # 3** #{ @game . id } **** #{ Time . now . strftime ( " %Y-%m-%d %H:%M:%S.%L " ) } " )
@g = Gitlab . client
last_content = @g . files ( @myshixun . gpid , @path , " master " ) . try ( :content )
logger . info ( " file_update start # 4** #{ @game . id } **** #{ Time . now . strftime ( " %Y-%m-%d %H:%M:%S.%L " ) } " )
last_content = tran_base64_decode64 ( last_content )
content = if ( @myshixun . mirror_name . include? ( 'Python2.7' ) || @myshixun . mirror_name . include? ( 'Python3.6' ) || @myshixun . mirror_name . include? ( 'MachineLearning' ) ) && params [ :content ] . present?
params [ :content ] . gsub ( / \ t / , ' ' )
else
params [ :content ]
end
logger . info ( " file_update start # 5** #{ @game . id } **** #{ Time . now . strftime ( " %Y-%m-%d %H:%M:%S.%L " ) } " )
if content != last_content
code_file = @g . edit_file ( @myshixun . gpid , User . current . login , :content = > content , :file_path = > @path , :branch_name = > @rev , :commit_message = > " shixun exec " )
end
if record . present?
consume_time = format ( " %.3f " , ( Time . now . to_f - record . created_at . to_f ) ) . to_f
record . update_attributes! ( :file_update = > consume_time )
end
logger . info ( " file_update start # 6** #{ @game . id } **** #{ Time . now . strftime ( " %Y-%m-%d %H:%M:%S.%L " ) } " )
# status为2说明是重新评测
if @game . status == 2
code = CODES . sample ( 8 ) . join
resubmit = " #{ code } _ #{ @myshixun . id } "
end
if content != last_content && code_file . blank?
raise ( " update file failed " )
else
render :json = > { :success = > " success " , :resubmit = > resubmit }
end
end
rescue Exception = > e
render :json = > { :success = > " fail " , :contents = > " 实训云平台繁忙( 繁忙等级: 81) , 请稍后刷新并重试 " , :position = > @game . challenge . position , :had_done = > @game . had_done }
end
# json调用, 显示左边的隐藏具体详情@game 字段 msg
# 刷新右边的输出结果 @game out_put
def outputs_show
@output = Output . find ( params [ :game_output_id ] )
respond_to do | format |
format . js
end
end
# 获取评测的等待的时间
# res['waitNum'] 评测等待人数
# res['waitingTime'] 评测等待时间
# res['ableToCreate'] 0 表示在等待中 1 表示可执行 -1 表示超过最大等待人数
def get_waiting_time
shixun_tomcat = Redmine :: Configuration [ 'shixun_tomcat' ]
uri = " #{ shixun_tomcat } /bridge/game/getWaitingTime "
params = { :tpiID = > " #{ @myshixun . id } " , :first = > @_params [ :first ] . to_i }
res = uri_exec uri , params
logger . info ( " # # # # # # # # # # # # res: #{ res } " )
if ( res && res [ 'code' ] != 0 )
@message = " 实训云平台繁忙( 繁忙等级: 94) "
raise ( " 实训云平台繁忙( 繁忙等级: 94) " )
end
logger . info ( " # # # # # # # # # # # get_waiting_time: #{ params } " )
logger . info ( " # # # # # # # # # # # ableToCreate : #{ res [ 'ableToCreate' ] } " )
render :json = > { :result = > " success " , :ableToCreate = > res [ 'ableToCreate' ] , :waitNum = > res [ 'waitNum' ] , :waitingTime = > res [ 'waitingTime' ] , :position = > @game . challenge . position }
#render :json => {:result => "success", :ableToCreate => 1, :waitNum => 10, :waitingTime => 1324 }
rescue Exception = > e
render :json = > { :result = > " fail " , :contents = > '实训云平台繁忙( 繁忙等级: 94) , 请稍后刷新并重试' , :position = > @game . challenge . position }
end
# status 0: 未提交测评或者提交测评失败后报错; 1: 中间状态还没返回值; 2: 返回值并成功
# resubmit 唯一随机码,为了区分每一次重新评测结果
def game_build
#render :json => {:result => "success", :ableToCreate => 1, :waitNum => 13, :port => 41222 }
# 更新时间是为了TPM端显示的更新, 退出实训及访问实训的时候会更新
logger . info ( " game_build start # 1** #{ @game . id } **** #{ Time . now . strftime ( " %Y-%m-%d %H:%M:%S.%L " ) } " )
@myshixun . update_column ( :updated_at , Time . now )
game_challenge = @game . challenge
shixun = @myshixun . shixun
gitUrl = gitlab_url @myshixun
gitUrl = Base64 . urlsafe_encode64 ( gitUrl )
taskId = @game . id
#code = CODES.sample(8).join
# status为2说明是重新评测
if @game . status == 2
resubmit = @_params [ :resubmit ]
else
# 重新评测不影响已通关的实训状态
if @_params [ :first ] . to_i == 1
@game . update_attributes! ( :status = > 1 )
end
end
shixun_tomcat = Redmine :: Configuration [ 'shixun_tomcat' ]
step = game_challenge . try ( :position )
logger . info ( " game_build start # 2** #{ @game . id } **** #{ Time . now . strftime ( " %Y-%m-%d %H:%M:%S.%L " ) } " )
testSet = [ ]
game_challenge . test_sets . each do | test_set |
input = test_set . input . nil? ? " " : test_set . input . gsub ( " \r \n " , " \n " )
output = test_set . output . nil? ? " " : test_set . output . gsub ( " \r \n " , " \n " )
test_cases = { :input = > input , :output = > output }
testSet << test_cases
end
logger . info ( " game_build start # 3** #{ @game . id } **** #{ Time . now . strftime ( " %Y-%m-%d %H:%M:%S.%L " ) } " )
testCases = Base64 . urlsafe_encode64 ( testSet . to_json ) unless testSet . blank?
mirror_repository = shixun . mirror_repositories . where ( :main_type = > 1 ) . first
resource_limit = " echo 'ulimit -f #{ mirror_repository . resource_limit } ' >> /root/.bashrc ; source /root/.bashrc \n "
tpmScript = shixun . evaluate_script . nil? ? " " : Base64 . urlsafe_encode64 ( ( resource_limit + shixun . evaluate_script ) . gsub ( " \r \n " , " \n " ) )
# 注意:这个地方的参数写的时候不能换行
params = { :tpiID = > " #{ @myshixun . id } " , :tpiGitURL = > " #{ gitUrl } " , :buildID = > " #{ taskId } " , :instanceChallenge = > " #{ step } " ,
:testCases = > " #{ testCases } " , :resubmit = > " #{ resubmit } " , :times = > @_params [ :first ] . to_i , :podType = > shixun . webssh ,
:containers = > " #{ Base64 . urlsafe_encode64 ( container_limit ( shixun . mirror_repositories ) ) } " , :tpmScript = > " #{ tpmScript } " ,
:timeLimit = > " #{ shixun . main_mirror . try ( :time_limit ) } " }
# 评测有文件输出的需要特殊传字段 path: 表示文件存储的位置
params [ 'file' ] = Base64 . urlsafe_encode64 ( { :path = > " #{ game_challenge . picture_path } " } . to_json ) if game_challenge . picture_path . present?
# needPortMapping: web类型需要pod端口映射
params [ :needPortMapping ] = 8080 if @myshixun . mirror_name . include? ( " Web " )
# uri = URI("#{shixun_tomcat}/bridge/game/gameEvaluate")
logger . info ( " game_build start # 4** #{ @game . id } **** #{ Time . now . strftime ( " %Y-%m-%d %H:%M:%S.%L " ) } " )
uri = " #{ shixun_tomcat } /bridge/game/gameEvaluate "
res = uri_exec uri , params
if ( res && res [ 'code' ] != 0 )
@message = " 实训云平台繁忙( 繁忙等级: 86) "
raise ( " 实训云平台繁忙( 繁忙等级: 86) " )
end
logger . info ( " game_build start # 5****** #{ Time . now . strftime ( " %Y-%m-%d %H:%M:%S.%L " ) } " )
render :json = > { :result = > " success " , :resubmit = > resubmit , :ableToCreate = > res [ 'ableToCreate' ] , :waitNum = > res [ 'waitNum' ] , :waitingTime = > res [ 'waitingTime' ] , :position = > @game . challenge . position , :port = > res [ 'port' ] , :had_done = > @game . had_done }
logger . info ( " game_build start # 6****** #{ Time . now . strftime ( " %Y-%m-%d %H:%M:%S.%L " ) } " )
rescue Exception = > e
if resubmit . nil?
@game . update_attributes! ( :status = > 0 )
end
logger . error ( " # # # # # # # # # # # # # # # # # # # " + e . message )
render :json = > { :result = > 'fail' , :contents = > " 实训云平台繁忙( 繁忙等级: 86) , 请稍后刷新并重试 " , :position = > game_challenge . position , :had_done = > @game . had_done }
end
# @myshixun -status 1:完成实训
# 全部通关奖励1000分
# retry_status 评测的唯一标识,重新评测对以前已产生的结果不造成影响
# params[:resubmit] 不为空表示已通过该关后重新评测, 重新评测必须是通过该关后才能执行
# @had_done 1 通关所有关
# port: PHP/Web会有端口号, 其他语言返回-1
# params[:time_out] 超时
def game_status
logger . info ( " game_status start # 1** #{ @game . id } **** #{ Time . now . strftime ( " %Y-%m-%d %H:%M:%S.%L " ) } " )
if ( params [ :time_out ] == " false " ) && ( ( params [ :resubmit ] . blank? && @game . status != 2 && @game . status != 0 ) || ( params [ :resubmit ] . present? && ( params [ :resubmit ] != @game . resubmit_identifier ) ) )
render :json = > { :status = > 1 }
return
end
game_challenge = @game . challenge
had_done = @game . had_done
resubmit_identifier = @game . resubmit_identifier
shixun = @myshixun . shixun
port = params [ :port ]
score = 0
user_gold = 0 #用户奖励金币
tag_count = 0
logger . info ( " # # # # # resubmit_identifier is #{ resubmit_identifier } " )
logger . info ( " game_status start # 2** #{ @game . id } **** #{ Time . now . strftime ( " %Y-%m-%d %H:%M:%S.%L " ) } " )
if params [ :resubmit ] . blank? # 非重新评测
# 通过当前一关
if @game . status == 2
if ! @game . answer_open && shixun . status > 1
score = game_challenge . score
user_gold = game_challenge . score
tag_count = game_challenge . challenge_tags . count
elsif shixun . status > 1 && @game . answer_open
score = - game_challenge . score . to_i
tag_count = 0
else
score = " +0 "
tag_count = 0
end
end
game_status = @game . status
else # 重新评测
if params [ :resubmit ] == resubmit_identifier # 本次重新评测结果已经返回并存入数据库
game_status = ( @game . retry_status == 2 ? 2 : 0 ) # retry_status 2: 成功 1: 失败
if game_status == 2 && had_done == 1 # 重新评测如果评测成功
had_done = 1
else
had_done = 0
end
else
# game_status 在前端有行为判断, 2表示通关; 0表示失败; 1表示评测中的中间状态
game_status = 1
had_done = 0
end
end
logger . info ( " game_status start # 3** #{ @game . id } **** #{ Time . now . strftime ( " %Y-%m-%d %H:%M:%S.%L " ) } " )
max_query_index = @game . outputs . first . try ( :query_index )
if max_query_index . present?
test_sets = TestSet . find_by_sql ( " SELECT o.actual_output, o.result, o.test_set_position, o.query_index,t.is_public,t.input, t.output, g.id as game_id, c.id as challenge_id FROM outputs o,games g ,challenges c,test_sets t where
g . id = #{@game.id} and o.query_index=#{max_query_index} and g.id = o.game_id and c.id= g.challenge_id and t.challenge_id = c.id and t.position =o.test_set_position order by o.query_index
" )
else
test_sets = TestSet . find_by_sql ( " SELECT t.is_public,t.input, t.output,t.position FROM games g ,challenges c,test_sets t where
g . id = #{@game.id} and c.id= g.challenge_id and t.challenge_id = c.id
" )
end
logger . info ( " game_status start # 4** #{ @game . id } **** #{ Time . now . strftime ( " %Y-%m-%d %H:%M:%S.%L " ) } " )
unless test_sets . blank?
total_test_sets = test_set_static_data ( test_sets )
end
logger . info ( " # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #{ @public_test_sets } " )
@test_sets_count = test_sets . count
@test_sets_hidden_count = test_sets . blank? ? 0 :test_sets . select { | test_set | test_set . is_public == false } . count
@test_sets_public_count = @test_sets_count - @test_sets_hidden_count
had_test = Output . where ( :game_id = > @game . id , :query_index = > ( @game . query_index - 1 ) )
@had_test_count = had_test . count
@had_passed_testsests_error_count = had_test . blank? ? 0 : had_test . select { | had_test | had_test . result == false } . count
@had_passed_testsests_error_count = @had_test_count - @had_passed_testsests_error_count
@had_passed_testsests_hidden_count = had_test . blank? ? 0 : had_test . select { | had_test | had_test . result == true && had_test . is_public == false } . count
@had_passed_testsests_public_count = had_test . blank? ? 0 : had_test . select { | had_test | had_test . result == true && had_test . is_public == true } . count
@final_score = ( ( shixun . try ( :status ) . to_i < = 1 ) ? 0 : @game . try ( :final_score ) . to_i )
picture = ( @game . picture_path . nil? ? 0 : @game . id )
if @myshixun . shixun . try ( :status ) < = 1 || ( @game . try ( :final_score ) . to_i != 0 && @game . answer_open? )
@gold = 0
else
if @game . answer_open? && @game . try ( :final_score ) . to_i == 0
@gold = - game_challenge . try ( :score ) . to_i
else
@gold = @game . try ( :final_score ) . to_i
end
end
#@gold = @myshixun.shixun.status <= 1 ? 0 : (@game.answer_open? && @game.final_score.to_i == 0 && @game.status == 2 ? -game_challenge.score.to_i : @game.final_score.to_i)
error_position = had_test . blank? ? nil : had_test . select { | had_test | had_test . result == false } . last
@latest_output = error_position . try ( :out_put ) . gsub ( / \ n / , '<br/>' ) . gsub ( / \ t / , ' ' ) unless error_position . try ( :out_put ) . blank?
logger . info ( " @compile_success # # # # # # # # # # # # # # # # # # #{ @compile_success } " )
@language = game_challenge . shixun . language
@mirror_name = @myshixun . mirror_name
power = ( User . current . manager_of_shixun? ( shixun ) || ( User . current . try ( :professional_certification ) && User . current . user_extensions . try ( :identity ) == 0 ) ) ? true : false
logger . info ( " game_status start # 5** #{ @game . id } **** #{ Time . now . strftime ( " %Y-%m-%d %H:%M:%S.%L " ) } " )
# 更新用户时间
if game_status == 0 || game_status == 2
record = EvaluateRecord . where ( :game_id = > @game . id ) . first
if record
front_js = format ( " %.3f " , ( Time . now . to_f - record . try ( :updated_at ) . to_f ) ) . to_f
consume_time = format ( " %.3f " , ( Time . now - record . created_at ) ) . to_f
record . update_attributes ( :consume_time = > consume_time , :front_js = > front_js )
end
end
# 记录前端总耗时
record = EvaluateRecord . where ( :game_id = > @game . id ) . first . try ( :consume_time )
logger . info ( " game_status start # 6** #{ @game . id } **** #{ Time . now . strftime ( " %Y-%m-%d %H:%M:%S.%L " ) } " )
render :json = > { test_sets : total_test_sets ,
test_sets_count : @test_sets_count ,
test_sets_hidden_count : @test_sets_hidden_count ,
test_sets_public_count : @test_sets_public_count ,
had_test_count : @had_test_count ,
had_passed_testsests_error_count : @had_passed_testsests_error_count ,
had_passed_testsests_hidden_count : @had_passed_testsests_hidden_count ,
had_passed_testsests_public_count : @had_passed_testsests_public_count ,
final_score : @final_score ,
gold : @gold ,
latest_output : @latest_output ,
status : game_status ,
had_done : had_done ,
language : @language ,
score : score ,
user_gold : user_gold ,
tag_count : tag_count ,
position : game_challenge . position ,
port : port ,
power : power ,
record : record ,
mirror_name : @mirror_name ,
picture : picture
}
end
# 选择题评测(选择题不需要重新评测)
# score 获得金币数 tag_count 技能数 right用户是否全对 answer_right全部选择题的正确性
def evaluating_choice
@game_challenge = @game . challenge
@challenges = Challenge . where ( :shixun_id = > @myshixun . shixun_id )
@shixun = @myshixun . shixun
score = 0
tag_count = 0
@right = true
answer_right = [ ]
@game_challenge . challenge_chooses . each_with_index do | choose , index |
correct = ( params [ :answer ] [ index ] == choose . standard_answer ) ? true : false
Output . create ( :game_id = > @game . id , :test_set_position = > choose . position , :actual_output = > params [ :answer ] [ index ] , :result = > correct , :query_index = > @game . query_index )
if @shixun . status > 1 && ! @game . answer_open
if correct
score += choose . score
tag_count += choose . challenge_tags . count
end
elsif @shixun . status > 1 && @game . answer_open
score -= choose . score
end
unless correct
@right = false
end
answer_right << correct
end
@had_done = @game . had_done
if @right && @game . status != 2
@game . update_attributes ( :status = > 2 , :end_time = > Time . now )
# 选择题最后一关, 更新status
if @had_done
@myshixun . update_attribute ( :status , 1 )
end
if @shixun . status > 1 && ! @game . answer_open
reward_grade ( @game . user , @game . id , 'Game' , @game_challenge . choose_score )
reward_experience ( @game . user , @game . id , 'Game' , @game_challenge . choose_score )
@game . update_attribute ( :final_score , @game_challenge . choose_score )
end
end
respond_to do | format |
format . js { redirect_to myshixun_game_path ( @game , :myshixun_id = > @myshixun , :choose = > @right ) }
end
end
def change_status
@game . update_attribute ( :status , 0 )
outputs = @game . outputs
if outputs . count == 0
outputs = " "
else
outputs = outputs . map { | result | [ result . code , result . id ] }
end
render :json = > { status : @game . status , output : " 服务器网络异常 " , results : outputs , had_done : 0 }
end
# 获取等待的任务数
# 如果没有等待任务页面上将不显示
# msg: -1 不存在等待的任务
# 如果该方法异常则直接返回0, 跳过等待
def waiting_info
begin
shixun_tomcat = Redmine :: Configuration [ 'shixun_tomcat' ]
params = { :buildID = > " #{ @game . id } " }
uri = URI ( " #{ shixun_tomcat } /jenkins-exec/api/getWaitingTime " )
res = uri_exec uri , params
if ( res && res [ 'code' ] != 0 )
raise ( " 获取等待任务数异常 " )
end
task_count = res [ 'msg' ] . to_i
task_count > 0 ? task_count : 0
render :json = > { task_count : task_count }
rescue
render :json = > { task_count : 0 }
end
end
# 自动推送下一个任务
# 从waiting_time发的请求则有type
def next_step
#unless show_next_stage?(@game, @myshixun.shixun.try(:status))
# render_403
#end
next_game = @game . next_game
next_game . update_attributes ( :status = > 0 , :open_time = > Time . now ) if next_game . status == 3
respond_to do | format |
format . js { redirect_to myshixun_game_path ( next_game , :myshixun_id = > @myshixun ) }
format . html { redirect_to myshixun_game_path ( next_game , :myshixun_id = > @myshixun ) }
end
end
def prev_step
prev_game = @game . prev_game
respond_to do | format |
format . js { redirect_to myshixun_game_path ( prev_game , :myshixun_id = > @myshixun ) }
format . html { redirect_to myshixun_game_path ( prev_game , :myshixun_id = > @myshixun ) }
end
end
# 获取答案,第一次查看需扣掉该关卡的积分
# 如果已看过,下次可以免费查看
# viewed 1: 直接查看 2: 弹框提示将要扣除积分, 确定后显示内容 3: 弹框提示分数不够
def answer
challenge = @game . challenge
@challenge_score = challenge . score . to_i
@answer = " "
# 已经开启过
@score = User . current . grade . to_i - @challenge_score
if ( params [ :choose ] == " true " )
challenge . challenge_chooses . each_with_index do | choose , index |
@answer += " 第 " + ( ( index + 1 ) . to_s ) + " 题:<br /> "
@answer += ( choose . answer . blank? ? choose . standard_answer : choose . answer )
@answer += " <br /><br /><br /> "
end
else
@answer = challenge . answer
end
if challenge . shixun . status < 2 || User . current . manager_of_shixun? ( challenge . shixun ) || @game . answer_open || ( challenge . st != 0 && @game . status == 2 )
@viewed = 1
else
if @score > = 0
@viewed = 2
else
@viewed = 3
end
end
respond_to do | format |
format . js
format . html
end
end
# web渲染
def web_display
path = @game . challenge . path . strip
port = ( 50000 + @game . myshixun_id ) . to_s
# 测试
#path = "src/step1/Helloworld.php"
#port = (50000+4116).to_s
@url = " http://106.75.96.108: " + port + '/' + path
respond_to do | format |
format . html { render :layout = > false }
end
end
def minus_score
@game_challenge = @game . challenge
@position = @game_challenge . position
user = User . current
challenge_score = @game_challenge . score . to_i
@answer = " "
if @game . challenge . st == 0
@answer = @game_challenge . answer
else
@game_challenge . challenge_chooses . each_with_index do | choose , index |
@answer += " 第 " + ( ( index + 1 ) . to_s ) + " 题:<br /> "
@answer += ( choose . answer . blank? ? choose . standard_answer : choose . answer )
@answer += " <br /><br /><br /> "
end
end
unless @game . answer_open
# 最终得分可能是负分
final_score = @game . final_score - challenge_score
@game . update_attributes! ( :answer_open = > true , :final_score = > final_score )
# 积分消耗情况统计
reward_grade ( user , @game . id , 'Answer' , - challenge_score )
@grades = final_score
end
end
def refresh_game_list
myshixun_id = params [ :myshixun_id ]
@myshixun = Myshixun . find_by_identifier ( myshixun_id )
# @challenges = Challenge.where(:shixun_id => @myshixun.shixun_id)
@challenges = Challenge . where ( :shixun_id = > @myshixun . shixun_id ) . includes ( :games ) . where ( " games.user_id = #{ @myshixun . user_id } " )
respond_to do | format |
format . js
end
end
def check_test_sets
user_grade = User . current . grade
@minus_grade = @game . challenge . score * 5
if user_grade > = @minus_grade
User . current . update_attribute ( :grade , user_grade - @minus_grade )
@game . update_attribute ( :test_sets_view , true )
# 扣分记录
Grade . create ( :user_id = > User . current . id , :container_id = > @game . id , :score = > - @minus_grade , :container_type = > " testSet " )
respond_to do | format |
format . js { redirect_to myshixun_game_path ( @game , :myshixun_id = > @myshixun , :test_sets_view = > true ) }
end
else
respond_to do | format |
format . js
end
end
end
def reset_original_code
@g = Gitlab . client
begin
@shixun = @myshixun . shixun
@path = params [ :path ] . try ( :strip )
game_code = GameCode . where ( :game_id = > @game . id , :path = > @path ) . first
GameCode . create ( :game_id = > @game . id , :path = > @path ) if game_code . blank?
content = game_code . try ( :original_code )
@arr_path = @game . challenge . path . split ( " ; " )
@rev = @rev . nil? ? " master " : @rev
content = @g . files ( @shixun . gpid , @path , @rev ) . try ( :content )
content = tran_base64_decode64 ( content )
update_gitlab_file ( content , @path , @rev , " file reset " )
file_content = @g . files ( @myshixun . gpid , @path , @rev ) . content
@content = tran_base64_decode64 ( file_content )
if @content . nil?
raise ( " 初始代码为空,代码重置失败 " )
end
rescue Exception = > e
@error_messages = e . message
end
respond_to do | format |
format . js
end
end
def system_update
@myshixun . update_attribute ( :system_tip , true )
render :json = > { :status = > 1 , :message = > " success " }
end
def reset_new_code
begin
@shixun = @myshixun . shixun
@g = Gitlab . client
@arr_path = params [ :path ]
@path = @arr_path [ 0 ] . try ( :strip )
@rev = @rev . nil? ? " master " : @rev
message = " file reset "
@arr_path . each do | path |
game_code = GameCode . where ( :game_id = > @game . id , :path = > path ) . first
content = game_code . try ( :new_code )
if content . nil?
raise ( " 示例代码为空,代码重置失败 " )
end
update_gitlab_file ( content , path , @rev , message )
end
file_content = @g . files ( @myshixun . gpid , @path , @rev ) . content
@content = tran_base64_decode64 ( file_content )
if @content . nil?
raise ( " 示例代码为空,代码重置失败 " )
# @entries = @repository.entries(@path, @rev)
end
respond_to do | format |
format . js
end
rescue Exception = > e
@error_messages = e . message
end
end
private
def update_gitlab_file content , path , rev , message
code_file = @g . edit_file ( @myshixun . gpid , User . current . login , :content = > content , :file_path = > path , :branch_name = > rev , :commit_message = > " #{ message } " )
if code_file . nil?
raise ( " 网络异常,文件更新失败 " )
end
end
def test_set_static_data test_sets
test_result = [ ]
unless test_sets . blank?
test_sets . each do | test_set |
actual_output = test_set . attributes . count > 4 ? test_set . try ( :actual_output ) : nil
result = test_set . attributes . count > 4 ? test_set . try ( :result ) : nil
#actual_output = Base64.encode64(actual_output)
compile_success = ( actual_output . blank? || actual_output . downcase . match ( / error / ) . present? ) ? 0 : 1
public_result = { :is_public = > ( test_set . is_public ? 1 : 0 ) , :result = > result , :input = > test_set . input ,
:actual_output = > actual_output , :output = > test_set . output , :compile_success = > compile_success }
test_result << public_result . to_json
end
end
test_result = test_result . blank? ? test_result : test_result . join ( " , " )
return test_result . gsub ( / < \/ script> / , '<//script>' )
end
def entry_and_raw ( is_raw )
@entry = @repository . entry ( @path , @rev )
( show_error_not_found ; return ) unless @entry
# If the entry is a dir, show the browser
( show ; return ) if @entry . is_dir?
@content = @repository . cat ( @path , @rev )
( show_error_not_found ; return ) unless @content
if is_raw || ( @content . size && @content . size > Setting . file_max_size_displayed . to_i . kilobyte ) || ! is_entry_text_data? ( @content , @path )
# Force the download
send_opt = { :filename = > filename_for_content_disposition ( @path . split ( '/' ) . last ) }
send_type = Redmine :: MimeType . of ( @path )
send_opt [ :type ] = send_type . to_s if send_type
send_opt [ :disposition ] = ( Redmine :: MimeType . is_type? ( 'image' , @path ) && ! is_raw ? 'inline' : 'attachment' )
send_data @content , send_opt
else
# Prevent empty lines when displaying a file with Windows style eol
# TODO: UTF-16
# Is this needs? AttachmentsController reads file simply.
@content . gsub! ( " \r \n " , " \n " )
@changeset = @repository . find_changeset_by_name ( @rev )
end
end
def is_entry_text_data? ( ent , path )
# UTF-16 contains "\x00".
# It is very strict that file contains less than 30% of ascii symbols
# in non Western Europe.
return true if Redmine :: MimeType . is_type? ( 'text' , path )
# Ruby 1.8.6 has a bug of integer divisions.
# http://apidock.com/ruby/v1_8_6_287/String/is_binary_data%3F
return false if ent . is_binary_data?
true
end
def find_repository
@repository = @myshixun . repository
render_404 if @myshixun . gpid . nil?
@path = params [ :path ] . is_a? ( Array ) ? params [ :path ] . join ( '/' ) : params [ :path ] . to_s
@g = Gitlab . client
@g_project = @g . project ( @myshixun . gpid )
@g_default_branch = @g_project . default_branch
# gitlab端获取默认分支
@rev = params [ :rev ] . blank? ? @g_default_branch : params [ :rev ] . to_s . strip
rescue ActiveRecord :: RecordNotFound
render_404
end
def allowd_manager
render_403 unless ( User . current . manager_of_myshixun? ( @myshixun ) || User . current . admin? || User . current . id == @myshixun . shixun . try ( :user_id ) )
end
# 判断成员是否允许查看
def allowd_view
if @myshixun . shixun . try ( :status ) == 2 && @game . status == 3 && User . current . id != @myshixun . shixun . try ( :user_id )
render_403
end
# render_403 if (@game.status == 3 && User.current.id != @myshixun.shixun.try(:user_id))
end
def find__shixun_language
language = @myshixun . shixun . try ( :language )
@language = language_switch ( language )
end
# Find myshixun of id params[:id]
def find_myshixun
myshixun_id = params [ :myshixun_id ] || ( params [ :game ] && params [ :game ] [ :myshixun_id ] )
@myshixun = Myshixun . find_by_identifier ( myshixun_id )
if @myshixun . nil?
render_404
return
end
rescue ActiveRecord :: RecordNotFound
render_404
end
def find_game
# myshixun_id = params[:myshixun_id]
@game = Game . find_by_identifier ( params [ :id ] )
if @game . nil?
render_404
return
end
@myshixun = @game . myshixun
rescue ActiveRecord :: RecordNotFound
render_404
end
end