From a8dce5e520bf0d7a404e0cf9d89bbc3778cd29cc Mon Sep 17 00:00:00 2001 From: yuanke <249218296@qq.com> Date: Thu, 14 Apr 2016 11:29:22 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BB=A3=E7=A0=81=E6=9F=A5=E9=87=8D=E5=8A=9F?= =?UTF-8?q?=E8=83=BD=E5=A2=9E=E5=8A=A0,=E7=AE=A1=E7=90=86=E5=91=98?= =?UTF-8?q?=E7=95=8C=E9=9D=A2=E5=A2=9E=E5=8A=A0=E4=BB=A3=E7=A0=81=E6=B5=8B?= =?UTF-8?q?=E8=AF=95=E5=88=97=E8=A1=A8.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controllers/admin_controller.rb | 10 + app/controllers/courses_controller.rb | 61 ++ app/controllers/student_work_controller.rb | 121 ++- app/models/homework_common.rb | 2 +- app/models/student_work.rb | 2 +- app/views/admin/code_work_tests.html.erb | 96 +++ .../courses/_compare_code_tips_1.html.erb | 101 +++ .../courses/_compare_code_tips_2.html.erb | 22 + app/views/courses/_show_compare_code.html.erb | 16 + app/views/courses/code_repeat.html.erb | 79 ++ app/views/courses/show_comparecode.js.erb | 101 +++ .../student_work/_evaluation_work.html.erb | 6 +- .../_programing_work_show.html.erb | 13 +- .../student_work/_student_work_list.html.erb | 146 ++++ .../student_work/show_allwork_test.html.erb | 2 + .../users/new_user_commit_homework.html.erb | 23 +- app/views/users/user_commit_homework.html.erb | 22 +- config/locales/zh.yml | 5 +- config/routes.rb | 6 +- ...20160330094039_add_simi_id_to_homeworks.rb | 6 + ...95711_add_simi_time_to_homework_commons.rb | 5 + db/schema.rb | 5 +- lib/redmine.rb | 1 + public/assets/codemirror/merge.css | 113 +++ public/assets/codemirror/merge.js | 774 ++++++++++++++++++ public/javascripts/course.js | 5 +- public/javascripts/homework.js | 3 +- public/stylesheets/application.css | 23 + public/stylesheets/courses.css | 11 + 29 files changed, 1737 insertions(+), 43 deletions(-) create mode 100644 app/views/admin/code_work_tests.html.erb create mode 100644 app/views/courses/_compare_code_tips_1.html.erb create mode 100644 app/views/courses/_compare_code_tips_2.html.erb create mode 100644 app/views/courses/_show_compare_code.html.erb create mode 100644 app/views/courses/code_repeat.html.erb create mode 100644 app/views/courses/show_comparecode.js.erb create mode 100644 app/views/student_work/show_allwork_test.html.erb create mode 100644 db/migrate/20160330094039_add_simi_id_to_homeworks.rb create mode 100644 db/migrate/20160330095711_add_simi_time_to_homework_commons.rb create mode 100644 public/assets/codemirror/merge.css create mode 100644 public/assets/codemirror/merge.js diff --git a/app/controllers/admin_controller.rb b/app/controllers/admin_controller.rb index c7aa42b9e..8009feac1 100644 --- a/app/controllers/admin_controller.rb +++ b/app/controllers/admin_controller.rb @@ -556,4 +556,14 @@ class AdminController < ApplicationController end end + #代码测试列表 + def code_work_tests + @code_work_tests = StudentWorkTest.find_by_sql("select a.* ,b.id as homeworkid,d.language from student_work_tests as a , homework_commons as b ,student_works as c, homework_detail_programings as d where a.student_work_id = c.id and b.id = c.homework_common_id and c.homework_common_id = d.homework_common_id order by a.created_at desc") + #@code_work_tests = StudentWorkTest.order('created_at desc') + @code_work_tests = paginateHelper @code_work_tests,30 + @page = (params['page'] || 1).to_i - 1 + respond_to do |format| + format.html + end + end end diff --git a/app/controllers/courses_controller.rb b/app/controllers/courses_controller.rb index 515b94392..942b3b2d2 100644 --- a/app/controllers/courses_controller.rb +++ b/app/controllers/courses_controller.rb @@ -885,6 +885,7 @@ class CoursesController < ApplicationController @course_activities = course_activities.order('updated_at desc').limit(10).offset(@page * 10) end @type = params[:type] + respond_to do |format| format.js format.html{render :layout => 'base_courses'} @@ -925,6 +926,66 @@ class CoursesController < ApplicationController end end + def search_homework_member homeworks,name + if name == "" + select_homework = homeworks + else + name = name.downcase + select_homework = homeworks.select{ |homework| + homework.user[:login].to_s.downcase.include?(name) || homework.user.user_extensions[:student_id].to_s.downcase.include?(name) || (homework.user[:lastname].to_s.downcase + homework.user[:firstname].to_s.downcase).include?(name) + } + end + select_homework + end + + # 作业查重 + def code_repeat + #代码查重新加的 + @order,@b_sort,@name,@group = params[:order] || "score",params[:sort] || "desc",params[:name] || "",params[:group] + + @is_teacher = User.current.allowed_to?(:as_teacher,@course) || User.current.admin? + @homework = HomeworkCommon.find params[:homework] + #order("#{@order} #{@b_sort}" + @student_works = search_homework_member @homework.student_works.select("student_works.*,IF(final_score is null,null,IF(final_score = 0, 0, final_score - absence_penalty - late_penalty)) as score").order("simi_value desc"),@name + + @works_hash = {} + + @student_works.each do |tmpwork| + @works_hash[tmpwork.id] = tmpwork + end + + #respond_to do |format| + #format.html {render :layout => 'base_courses'} + #end + end + + def show_comparecode + + src_id = params[:src_id] + dst_id = params[:dst_id] + + src_work = StudentWork.where("id =?", src_id).first + + @homework = HomeworkCommon.find params[:homework_id] + + @src_code = src_work.description + src_user = User.where("id =?", src_work.user_id).first + + @src_username = src_user.try(:realname) != " " ? src_user.lastname + src_user.firstname : src_user.try(:login) + + #descriotion user name + + dst_work = StudentWork.where("id =?", dst_id).first + @dst_code = dst_work.description + dst_user = User.where("id =?", dst_work.user_id).first + + @dst_username = dst_user.try(:realname) != " " ? dst_user.lastname + dst_user.firstname : dst_user.try(:login) + + respond_to do |format| + format.js + end + end + #根据已有课程复制课程 #param id:已有课程ID def copy_course diff --git a/app/controllers/student_work_controller.rb b/app/controllers/student_work_controller.rb index 32867090c..ae78bf920 100644 --- a/app/controllers/student_work_controller.rb +++ b/app/controllers/student_work_controller.rb @@ -5,7 +5,7 @@ class StudentWorkController < ApplicationController include ApplicationHelper require 'bigdecimal' require "base64" - before_filter :find_homework, :only => [:new, :index, :create, :student_work_absence_penalty, :absence_penalty_list, :evaluation_list, :program_test,:program_test_ex,:set_score_rule,:forbidden_anonymous_comment,:delete_work,:new_student_work_project,:student_work_project,:cancel_relate_project,:search_course_students] + before_filter :find_homework, :only => [:new, :index, :create, :student_work_absence_penalty, :absence_penalty_list, :evaluation_list, :program_test,:program_test_ex,:code_repeattest,:set_score_rule,:forbidden_anonymous_comment,:delete_work,:new_student_work_project,:student_work_project,:cancel_relate_project,:search_course_students] before_filter :find_work, :only => [:edit, :update, :show, :destroy, :add_score, :praise_student_work,:retry_work,:revise_attachment] before_filter :member_of_course, :only => [:new, :create, :show, :add_score, :praise_student_work] before_filter :author_of_work, :only => [:edit, :update, :destroy] @@ -81,6 +81,8 @@ class StudentWorkController < ApplicationController #根据传入的tIndex确定是第几次测试 #之后如果觉得很卡 可以改成将结果传回JS再以参数形式传回来 def program_test_ex + tStarttime = Time.now + is_test = params[:is_test] == 'true' resultObj = {status: 0, results: [], error_msg: '', time: Time.now.strftime('%Y-%m-%d %T'),tseq:1,tcount:1,testid:1} #保存每测试一次返回的结果 @@ -134,6 +136,16 @@ class StudentWorkController < ApplicationController end #每次从数据库取出上次的结果加上本次的结果再存入数据库 + tEndtime = Time.now + tUsedtime = (tEndtime.to_i-tStarttime.to_i)*1000+(tEndtime.usec - tStarttime.usec)/1000 + + if result["status"].to_i != -2 + result["results"].first['user_wait'] = tUsedtime + end + + if result["results"][0]["status"].to_i == 2 + result["status"] = 2 + end status = result["status"] if index == 1 student_work_test = student_work.student_work_tests.build(status: status, @@ -162,6 +174,11 @@ class StudentWorkController < ApplicationController resultObj[:index] = student_work.student_work_tests.count end + tEndtime = Time.now + tUsedtime = (tEndtime.to_i-tStarttime.to_i)*1000+(tEndtime.usec - tStarttime.usec)/1000 + + logger.debug "program_test_ex user wait time = #{tUsedtime} 毫秒" + #渲染返回结果 render :json => resultObj end @@ -169,6 +186,106 @@ class StudentWorkController < ApplicationController end end + #找出该作业的所有提交作业 + def find_all_student_work_by_homeid() + all_studentwork = StudentWork.where("homework_common_id =?", @homework.id) + + all_studentwork + end + + def request_code_repeattest(src) + url = "#{Redmine::Configuration['jplag_server']}api/realtime_test.json" + + factor = [] + src.each do |test| + factor << {work_id: test.id, des: test.description,created_at:test.created_at.to_i} + end + + solutions = { + homeid:@homework.id, + language:@homework.homework_detail_programing.language, + factor: factor + } + uri = URI(url) + body = solutions.to_json + + logger.debug "send body" + logger.debug body + + res = Net::HTTP.new(uri.host, uri.port).start do |client| + request = Net::HTTP::Post.new(uri.path) + request.body = body + request["Content-Type"] = "application/json" + client.request(request) + end + + JSON.parse(res.body) + end + + #代码查重 status: 0完成 -2不需要查重 -1查重失败不支持该语言 + def code_repeattest + tStarttime = Time.now + logger.debug "code_repeattest start is #{tStarttime}}" + resultObj = {status: -2} + + @homework = HomeworkCommon.find params[:homework] + + all_studentwork = find_all_student_work_by_homeid() + + if all_studentwork == nil + resultObj[:status] = -2 + elsif all_studentwork.count <= 1 + resultObj[:status] = -2 + else + + #@homework.homework_detail_programing.language、id、description + logger.debug "time1 is #{Time.now.usec} " + result = request_code_repeattest(all_studentwork) + logger.debug "time2 is #{Time.now.usec} " + + resultObj[:status] = result['status'].to_i + # resultObj[:results] = result['results'] + + #Time.now, simi_id = simiworkid , simi_value = simivalue + if resultObj[:status] == 0 + @homework.simi_time = Time.now + resultObj[:comparetime] = @homework.simi_time + @homework.update_column('simi_time', @homework.simi_time) + + logger.debug "time3 is #{Time.now.usec} " + result['results'].each do |key,value| + if value['simiworkid'].to_i > 0 + @student_work = StudentWork.where("id =?", key.to_i).first + @student_work.update_column('simi_id', value['simiworkid'].to_i) + @student_work.update_column('simi_value', value['simivalue'].to_i) + end + # sqlstr = "update student_works set simi_id=#{value['simiworkid']},simi_value=#{value['simivalue']} where id=#{key.to_i} " + # dbh.execute(sqlstr) + + end + logger.debug "time4 is #{Time.now.usec} " + end + end + tEndtime = Time.now + logger.debug "code_repeattest end is #{tEndtime}}" + tUsedtime = (tEndtime.to_i-tStarttime.to_i)*1000000+(tEndtime.usec - tStarttime.usec) + logger.debug "code_repeattest userd utime is #{tUsedtime}" + render :json => resultObj + end + + def last_codecomparetime + resultObj = {status: 0} + @homework = HomeworkCommon.find params[:homework] + + #转换一下 + if @homework.simi_time != nil + resultObj[:comparetime] = Time.parse(@homework.simi_time.to_s).strftime("%Y-%m-%d %H:%M") + else + resultObj[:comparetime] = @homework.simi_time + end + + render :json => resultObj + end def index # 作业消息状态更新 @@ -351,6 +468,7 @@ class StudentWorkController < ApplicationController render_403 return end + @student_work_count = (search_homework_member @homework.student_works.select("student_works.*,IF(final_score is null,null,IF(final_score = 0, 0, final_score - absence_penalty - late_penalty)) as score").order("#{@order} #{@b_sort}"),@name).count end @@ -1152,6 +1270,7 @@ class StudentWorkController < ApplicationController request["Content-Type"] = "application/json" client.request(request) end + JSON.parse(res.body) end diff --git a/app/models/homework_common.rb b/app/models/homework_common.rb index f8e222b0f..283fea058 100644 --- a/app/models/homework_common.rb +++ b/app/models/homework_common.rb @@ -1,7 +1,7 @@ #老师布置的作业表 #homework_type: 0:普通作业;1:匿评作业;2:编程作业 class HomeworkCommon < ActiveRecord::Base - # attr_accessible :name, :user_id, :description, :publish_time, :end_time, :homework_type, :late_penalty, :course_id + # attr_accessible :name, :user_id, :description, :publish_time, :end_time, :homework_type, :late_penalty, :course_id,:simi_time include Redmine::SafeAttributes include ApplicationHelper diff --git a/app/models/student_work.rb b/app/models/student_work.rb index 144f3859f..82b1ad4a1 100644 --- a/app/models/student_work.rb +++ b/app/models/student_work.rb @@ -1,6 +1,6 @@ #学生提交作品表 class StudentWork < ActiveRecord::Base - attr_accessible :name, :description, :homework_common_id, :user_id, :final_score, :teacher_score, :student_score, :teaching_asistant_score, :project_id, :is_test + attr_accessible :name, :description, :homework_common_id, :user_id, :final_score, :teacher_score, :student_score, :teaching_asistant_score, :project_id, :is_test, :simi_id, :simi_value belongs_to :homework_common belongs_to :user diff --git a/app/views/admin/code_work_tests.html.erb b/app/views/admin/code_work_tests.html.erb new file mode 100644 index 000000000..df7de6bf0 --- /dev/null +++ b/app/views/admin/code_work_tests.html.erb @@ -0,0 +1,96 @@ +

+ <%=l(:label_code_work_tests)%> +

+ +  + + +
+ + + + + + + + + + + + + + + <% @code_work_tests.each do |test| %> + "> + + + + + + + + + + <% end %> + +
+ 作业id + + 平均等待时间 + + 语言 + + 提交测试时间 + + 答题状态 + + 测试集数 + + 最小耗时 + + 最大耗时 +
+ <%=link_to(test.homeworkid, student_work_index_path(:homework => test.homeworkid))%> + + <% if test.status != -2 && test.results.first['user_wait'] %> + <% wait_time = 0 %> + <% test.results.each do |result| wait_time = wait_time + result['user_wait'] end %> + <%=(wait_time/test.results.count).to_s+"毫秒" %> + <% else %> + <%="未记录"%> + <% end %> + + <%=%W(C C++ Python Java).at(test.language.to_i - 1)%> + + <%=Time.parse(test.created_at.to_s).strftime("%Y-%m-%d %H:%M:%S")%> + + <% if test.status == 0 %> + <%= "答题正确" %> + <% elsif test.status == -2 %> + <%= "编译错误" %> + <% elsif test.status == 2 || test.results.last['status'] == 2 %> + <%= "超时" %> + <% else %> + <%= "答题错误" %> + <% end %> + + <% if test.status != -2 %> + <%=test.results.count%> + <% end %> + + <% if test.status != -2 %> + <%test.results = test.results.sort_by {|result| result['time_used'] }%> + <%=test.results.first['time_used'] == 0 ? "1毫秒":test.results.first['time_used'].to_s+"毫秒"%> + <% end %> + + <% if test.status != -2 %> + <%=test.results.last['time_used'] == 0 ? "1毫秒":test.results.last['time_used'].to_s+"毫秒"%> + <% end %> +
+
+ + + +<% html_title(l(:label_code_work_tests)) -%> \ No newline at end of file diff --git a/app/views/courses/_compare_code_tips_1.html.erb b/app/views/courses/_compare_code_tips_1.html.erb new file mode 100644 index 000000000..696c40a48 --- /dev/null +++ b/app/views/courses/_compare_code_tips_1.html.erb @@ -0,0 +1,101 @@ +
+
+ <%if @homework.simi_time != nil %> +

<%="您上次查重的时间为"+Time.parse(@homework.simi_time.to_s).strftime("%Y-%m-%d %H:%M")%>

+ <%end%> + +
+
+
+ + + \ No newline at end of file diff --git a/app/views/courses/_compare_code_tips_2.html.erb b/app/views/courses/_compare_code_tips_2.html.erb new file mode 100644 index 000000000..f926a1a84 --- /dev/null +++ b/app/views/courses/_compare_code_tips_2.html.erb @@ -0,0 +1,22 @@ +
+
+

<%=des%>

+
+ 确定 +
+
+
+
+ + + \ No newline at end of file diff --git a/app/views/courses/_show_compare_code.html.erb b/app/views/courses/_show_compare_code.html.erb new file mode 100644 index 000000000..39f8e0565 --- /dev/null +++ b/app/views/courses/_show_compare_code.html.erb @@ -0,0 +1,16 @@ + +<% content_for :header_tags do %> + <%= javascript_include_tag "/assets/codemirror/codemirror_python_ruby_c" %> + <%= stylesheet_link_tag "/assets/codemirror/codemirror" %> + <%= stylesheet_link_tag "/assets/codemirror/merge" %> + <%= javascript_include_tag "https://cdnjs.cloudflare.com/ajax/libs/diff_match_patch/20121119/diff_match_patch.js"%> + <%= javascript_include_tag "/assets/codemirror/merge" %> +<% end %> + +
+

<%=src_name%>

+

<%=dst_name%>

+ + +
+
diff --git a/app/views/courses/code_repeat.html.erb b/app/views/courses/code_repeat.html.erb new file mode 100644 index 000000000..9e026c293 --- /dev/null +++ b/app/views/courses/code_repeat.html.erb @@ -0,0 +1,79 @@ +
+

查重结果

+
+ + + + <%if @homework.homework_type == 2 %> + <% @student_works.each do |student_work|%> + + <%end%> + <%end%> +
+
+
+ + \ No newline at end of file diff --git a/app/views/courses/show_comparecode.js.erb b/app/views/courses/show_comparecode.js.erb new file mode 100644 index 000000000..5cfae9428 --- /dev/null +++ b/app/views/courses/show_comparecode.js.erb @@ -0,0 +1,101 @@ +$("#ajax-modal").html('<%= escape_javascript( render :partial => 'courses/show_compare_code' ,:locals => {:src_code=> @src_code,:src_name=> @src_username,:dst_name=> @dst_username, :dst_code=> @dst_code,})%>'); +showModal('ajax-modal', '1250px'); +$('#ajax-modal').siblings().remove(); +$('#ajax-modal').before(""); +$('#ajax-modal').parent().css("top","20%").css("left","20%").css("position","absolute"); +//$('#ajax-modal').parent().addClass("resourceUploadPopup"); +$('#ajax-modal').css("padding-left","16px").css("padding-bottom","16px").css("padding-top","10px"); + +function closeModal(){ + hideModal($(".program-compare-code")); +} + +var program_name = "text/x-csrc"; +var language = <%= @homework.language.to_i %>; +if (language == 1) { + program_name = 'text/x-csrc'; +} else if(language==2){ + program_name = 'text/x-c++src'; +}else if(language==3){ + program_name = 'text/x-cython'; +} else if(language==4){ + program_name = 'text/x-java'; +} +// +//var editor_1 = CodeMirror(document.getElementById("program-code_1"), { +// mode: {name: program_name, +// version: 2, +// singleLineStringErrors: false}, +// lineNumbers: true, +// indentUnit: 2, +// matchBrackets: true, +// readOnly: true, +// value: $("#program-src_1").text() +// } +//); +// +//var editor_2 = CodeMirror(document.getElementById("program-code_2"), { +// mode: {name: program_name, +// version: 2, +// singleLineStringErrors: false}, +// lineNumbers: true, +// indentUnit: 2, +// matchBrackets: true, +// readOnly: true, +// value: $("#program-src_2").text() +// } +//); + +var value, orig1, orig2, dv, panes = 2, highlight = true, connect = null, collapse = false; +function initUI() { + if (value == null) return; + var target = document.getElementById("program-compare-code"); + target.innerHTML = ""; + dv = CodeMirror.MergeView(target, { + value: value, + origLeft: panes == 3 ? orig1 : null, + orig: orig2, + lineNumbers: true, + mode: program_name, + highlightDifferences: highlight, + connect: connect, + collapseIdentical: collapse + }); +} + +function toggleDifferences() { + dv.setShowDifferences(highlight = !highlight); +} + + +value = $("#program-src_1").text(); +orig1 = $("#program-src_1").text(); +orig2 = $("#program-src_2").text(); +initUI(); + + +function mergeViewHeight(mergeView) { + function editorHeight(editor) { + if (!editor) return 0; + return editor.getScrollInfo().height; + } + return Math.max(editorHeight(mergeView.leftOriginal()), + editorHeight(mergeView.editor()), + editorHeight(mergeView.rightOriginal())); +} + +function resize(mergeView) { + var height = mergeViewHeight(mergeView); + for(;;) { + if (mergeView.leftOriginal()) + mergeView.leftOriginal().setSize(null, height); + mergeView.editor().setSize(null, height); + if (mergeView.rightOriginal()) + mergeView.rightOriginal().setSize(null, height); + + var newHeight = mergeViewHeight(mergeView); + if (newHeight >= height) break; + else height = newHeight; + } + mergeView.wrap.style.height = height + "px"; +} \ No newline at end of file diff --git a/app/views/student_work/_evaluation_work.html.erb b/app/views/student_work/_evaluation_work.html.erb index f97a8dd2d..1e96a2771 100644 --- a/app/views/student_work/_evaluation_work.html.erb +++ b/app/views/student_work/_evaluation_work.html.erb @@ -1,10 +1,10 @@