diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index a2e5948a..e3dd080f 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -1,7448 +1,7448 @@ -# encoding: utf-8 -# -# Redmine - project management software -# Copyright (C) 2006-2013 Jean-Philippe Lang -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - -require 'forwardable' -require 'cgi' -require 'iconv' -module ApplicationHelper - include Redmine::WikiFormatting::Macros::Definitions - include Redmine::I18n - include GravatarHelper::PublicMethods - include Redmine::Pagination::Helper - include AvatarHelper - ## added by william - include PraiseTreadHelper - include CoursesHelper - - extend Forwardable - def_delegators :wiki_helper, :wikitoolbar_for, :heads_for_wiki_formatter - - # 课堂相关controller - def course_controller - ["courses", "homework_common", "student_work", "exercise", "poll", "boards", "messages", "graduation_topics", "graduation_tasks", - "graduation_works", "files"] - end - - # 实训课程相关controller - def subjects_controller - ["subjects", "stages"] - end - - # 实训路径相关controller - def shixuns_controller - ["shixuns", "challenges", "myshixuns", "games"] - end - - # 工程认证相关controller - def ecs_controller - ["ecs", "ec_courses", "ec_course_evaluations", "ec_course_supports", "ec_course_targets", "ec_graduation_requirements", - "ec_major_schools", "ec_majors", "ec_years"] - end - - def exercise_bank_json_data exercises - exercises.map do |exercise| - exercise_path = exercise_bank_path(exercise) - course_list = exercise.course_list.name - user_name = exercise.user.show_real_name - user_path = user_path(exercise.user) - exercise.attributes.dup.except("description", "is_public", "quotes", "container_id", "container_type", "created_at", "updated_at").merge({ - user_name: user_name, - user_path: user_path, - course_list: course_list, - exercise_path: exercise_path - }) - end - end - - def ac_pass?(standard_value, real_value) - standard_value && real_value && real_value >= standard_value ? "达成" : "未达成" - end - - def ec_pass?(standard_value, real_value) - standard_value && real_value && real_value >= standard_value ? 1 : 0 - end - - # 工程认证删除关联课堂 - def delete_course_correlation_ec_course_evaluations ec_course - ec_course_evaluations = ec_course.ec_course_evaluations.where(:is_course_type => true) - ec_course_evaluations.destroy_all if ec_course_evaluations - end - - def sync_ec_year_student_score ec_subitem, ce, year_students, students, works, position=1 - year_students.each do |year_student| - if students.map(&:id).include?(year_student.id) - work = works.where(:user_id => students.select{|s| s.id == year_student.id}[0].try(:user_id)).first - score = work.respond_to?(:work_score) ? work.try(:work_score) : work.try(:score) - else - score = 0 - end - ec_subitem.ec_student_achievements << EcStudentAchievement.new(:ec_year_student_id => year_student.id, :student_number => year_student.student_id, - :student_name => year_student.name, :score => score.to_f, - :position => position, :ec_course_evaluation_id => ce.id) - Rails.logger.info("############work_score:#{score}") - end - end - - # 同步在线课堂的考核标准和考核分项 - # ec_course: 工程认证的课程 - # course: 关联的在线课堂 - def sync_course_correlation_ec_course_evaluations ec_course, course - # 先删除之前的关联数据 - delete_course_correlation_ec_course_evaluations ec_course - - students = EcYearStudent.find_by_sql("SELECT eys.id, eys.student_id, eys.name, uxe.user_id FROM ec_year_students eys JOIN - (SELECT ue.student_id, ue.user_id FROM user_extensions ue JOIN students_for_courses sfc ON ue.`user_id` = sfc.`student_id` - WHERE sfc.`course_id` = #{course.id})uxe ON eys.student_id = uxe.student_id WHERE eys.ec_year_id = #{ec_course.ec_year_id}") - - year_students = ec_course.ec_year.ec_year_students - - # 实训作业模块 - shixun_models = course.homework_commons.where("homework_type = 4 and publish_time < '#{Time.now}'") - unless shixun_models.blank? - ce = EcCourseEvaluation.create(:name => "实训作业", :evluation_count => 1, :status => 2, :ec_course_id => ec_course.id, :is_course_type => true) - shixun_models.each do |shixun| - ec_subitem = EcCourseEvaluationSubitem.create(:name => shixun.name, :ec_course_evaluation_id => ce.id) - - sync_ec_year_student_score ec_subitem, ce, year_students, students, shixun.student_works - end - end - - # 普通作业模块 - common_models = course.homework_commons.where("homework_type = 1 and publish_time < '#{Time.now}'") - unless common_models.blank? - ce = EcCourseEvaluation.create(:name => "普通作业", :evluation_count => 1, :status => 2, :ec_course_id => ec_course.id, :is_course_type => true) - common_models.each do |common| - ec_subitem = EcCourseEvaluationSubitem.create(:name => common.name, :ec_course_evaluation_id => ce.id) - - sync_ec_year_student_score ec_subitem, ce, year_students, students, common.student_works - end - end - - # 分组作业模块 - group_models = course.homework_commons.where("homework_type = 3 and publish_time < '#{Time.now}'") - unless group_models.blank? - ce = EcCourseEvaluation.create(:name => "分组作业", :evluation_count => 1, :status => 2, :ec_course_id => ec_course.id, :is_course_type => true) - group_models.each do |group| - ec_subitem = EcCourseEvaluationSubitem.create(:name => group.name, :ec_course_evaluation_id => ce.id) - - sync_ec_year_student_score ec_subitem, ce, year_students, students, group.student_works - end - end - - # 试卷模块 - exercise_models = course.exercises.where("exercise_status > 1") - unless exercise_models.blank? - ce = EcCourseEvaluation.create(:name => "试卷", :evluation_count => 1, :status => 2, :ec_course_id => ec_course.id, :is_course_type => true) - exercise_models.each do |exercise| - ec_subitem = EcCourseEvaluationSubitem.create(:name => exercise.exercise_name, :ec_course_evaluation_id => ce.id) - - sync_ec_year_student_score ec_subitem, ce, year_students, students, exercise.exercise_users - end - end - - # 毕设任务模块 - task_models = course.graduation_tasks.where("publish_time < '#{Time.now}'") - unless task_models.blank? - ce = EcCourseEvaluation.create(:name => "毕设任务", :evluation_count => task_models.size, :status => 1, :ec_course_id => ec_course.id, :is_course_type => true) - task_models.each_with_index do |task, index| - ec_subitem = EcCourseEvaluationSubitem.create(:name => task.name, :ec_course_evaluation_id => ce.id) - - sync_ec_year_student_score ec_subitem, ce, year_students, students, task.graduation_works, index + 1 - end - end - end - - # 选用实训的学校情况 - def school_user_detail shixun - user_ids = shixun.myshixuns.pluck(:user_id) - schools = School.where(:id => UserExtensions.where(:user_id => user_ids).pluck(:school_id)) - school_size = schools.size - str = school_size > 0 ? "#{schools.limit(2).map(&:name).join("、")}等 #{school_size}所" : "0所" - end - - def shixun_json_data shixuns - shixuns.map do |shixun| - school_detail = school_user_detail shixun - preference = shixun.shixun_preference - shixun_path = shixun_path(shixun) - shixun.attributes.dup.merge({ - school_detail: school_detail, - preference: preference, - shixun_path: shixun_path - }) - end - end - - # 分班 - def member_group_name members, user_id - member = members.where(:user_id => user_id).first - group_name = member.try(:course_group_id).to_i == 0 ? '未分班' : member.course_group.name - end - - # 分班 - def new_member_group_name course_id, user_id - group_id = Member.where(:course_id => course_id, :user_id => user_id).pluck(:course_group_id).first - group_id == 0 ? '未分班' : CourseGroup.where(:id => group_id).pluck(:name).first - end - - # 分班id - def member_group_id members, user_id - member = members.where(:user_id => user_id).first - group_id = member.try(:course_group_id).to_i - end - - # 推荐实训 - def recommend_shixun shixun - shixun_id = ShixunTagRepertoire.where("tag_repertoire_id = #{shixun.tag_repertoires.first.present? ? shixun.tag_repertoires.first.try(:id) : 0} and shixun_id != #{shixun.id}").map(&:shixun_id) - shixuns = Shixun.select([:id, :name, :user_id, :status, :myshixuns_count, :trainee, :identifier]).where(:id => shixun_id, :status => 2, :hidden => 0).order("myshixuns_count desc").limit(3) - if shixuns.size < 3 - ids = shixuns.size == 0 ? "(-1)" : "(" + shixuns.map(&:id).join(',') + ")" - hot_shixuns = Shixun.select([:id, :name, :user_id, :status, :myshixuns_count, :trainee, :identifier]).where("status = 2 and hidden = 0 and id not in #{ids}").order("myshixuns_count desc").limit(3-shixuns.size) - return shixuns + hot_shixuns - else - return shixuns - end - end - - # 用户获取的技能标签 - def user_get_tags challenge_ids, user=User.current - tags = ChallengeTag.where(:challenge_id => user.games.where(:challenge_id => challenge_ids, :status => 2).pluck(:challenge_id)).pluck(:name).uniq - return tags - end - - # 所属路径 - def belongto_path shixun - Subject.where(:id => shixun.stage_shixuns.map(&:subject_id), :hidden => 0).limit(2) - end - - # 已授权老师加入示例课堂 - def join_ex_course user - course = Course.where(:id => 1309).first - if course - if course.members.where(:user_id => user.id).empty? - member = Member.new(:role_ids => [9], :user_id => user.id) - course.members << member - Tiding.create(:user_id => user.id, :trigger_user_id => 1, :container_id => course.id, :container_type => 'TeacherJoinCourse', :belong_container_id => course.id, :belong_container_type => "Course", :tiding_type => "System", :extra => "9") - end - end - end - -# 成员身份 - def member_zh_role member - role = "" - if member.roles.first - case member.roles.first.id - when 3 - role = "管理人员" - when 4 - role = "开发人员" - when 5 - role = "报告人员" - end - end - end - - def container_limit mirror_repositories - container = [] - mirror_repositories.each do |mr| - if mr.name.present? - container << {:image => mr.name, :cpuLimit => mr.cpu_limit, :memoryLimit => "#{mr.memory_limit}M", :type => mr.try(:main_type) == "1" ? "main" : "sub"} - end - end - return container.to_json - end - - # 实训作品列表的提交状态 - def list_work_status work, homework, member - if work.work_status == 0 - str = "未提交" - else - if work.compelete_status == 0 - setting_time = homework_group_setting homework, member.try(:course_group_id) - end_time = setting_time.end_time.present? ? setting_time.end_time : homework.end_time - if end_time > Time.now || (homework.allow_late && !homework.course.is_end) - str = "正在提交" - else - str = "延时提交" - end - else - if work.work_status == 1 - str = "按时提交" - else - str = "延时提交" - end - end - end - str - end - - # 试卷、问卷提交状态 - def ex_poll_work_status status - str = "" - case status - when 0 - str = "未提交" - when 1 - str = "按时提交" - when 2 - str = "延时提交" - end - str - end - - #传入分数,获取对应颜色 - def score_color score - if score - color = score >= 90 ? "color-red" : "color-green" - else - color = "color-grey" - end - color - end - - # 获取两断时间的日期差 - def time_between_days t1, t2 - Date.parse(t1.to_s) - Date.parse(t2.to_s) if t1.present? && t2.present? - end - - def update_valuate_time game_id, column - record = EvaluateRecord.where(:game_id => game_id).first - if record - consume_time = format("%.2f", (Time.now.to_f - record.created_at.to_f)).to_f - if column == "file_update" - record.update_attributes!(:file_update => consume_time) - elsif column == "pull" - record.update_attributes!(:consume_time => consume_time) - elsif column == "create_pod" - record.update_attributes!(:create_pod => consume_time) - elsif column == "pod_execute" - record.update_attributes!(:pod_execute => consume_time) - end - end - end - - # TPM查看权限 - # result一般为页面权限 - def shixun_view_allow shixun, result = nil - if User.current.manager_of_shixun?(shixun) - result ? false : true - else - if shixun.status == 0 || (shixun.use_scope == 1 && !shixun.schools.map(&:name).include?(User.current.school_name)) - result ? true : (render_403) - end - end - end - - # 判断TPM的代码是否被修改了 - # 判断依据是看tpm的最新提交记录和tpi数据库中存储的commit_id是否一致 - def repository_is_modified myshixun, shixun_gpid - g = Gitlab.client - myshixun_commit_id = myshixun.commit_id - if myshixun_commit_id.blank? - myshixun_commit_id = g.commits(myshixun.gpid).last.try(:id) - myshixun.update_column(:commit_id, myshixun_commit_id) - end - shixun_commit_id = g.commits(shixun_gpid).first.try(:id) - Rails.logger.warn("###############shixun_commit_id is #{shixun_commit_id}") - Rails.logger.warn("###############myshixun_commit_id is #{myshixun.commit_id}") - result = myshixun_commit_id != shixun_commit_id ? true :false - return result - end - - # 定义当前关卡是否有权开启下一关 - # :实训若发布了,必须通过当前关卡才能查看下一关 - # :未发布的实训,除了最后一关,其它的关卡都可以进入下一关 - def show_next_stage?(game, shixun_status) - if game.is_final_game? || ([2,3].include?(shixun_status.to_i) && game.try(:status) != 2) - false - else - true - end - end - - # 适用与已经用url_safe编码后,回调字符串形式 - def tran_base64_decode64 str - if str.blank? - str - else - s_size = str.size % 4 - if s_size != 0 - str += "=" * (4 - s_size) - end - Base64.decode64(str.tr("-_", "+/")).force_encoding("utf-8") - end - end - - def challenge_path path - cha_path = path.present? ? path.split(";") : [] - cha_path = cha_path.reject(&:blank?)[0].try(:strip) - cha_path - end - - def open_webssh - # 如果我webssh类型, 开启webssh - jenkins_shixuns = Redmine::Configuration['jenkins_shixuns'] - uri = URI("#{jenkins_shixuns}/jenkins-exec/webssh/getConnectInfo") - user_id = User.current.id - params = {userID:user_id} - res = uri_exec uri, params - return [host, port, username, password] - end - - # 中间层启动那种语言容器的类型 - # language 语言 exec_path 需要编译的文件路径 - def post_tomcat_language language, exec_path - if language == "Html" && !exec_path.blank? - case exec_path.split(".")[1].downcase - when "c" - "C" - when "cpp" - 'C++' - when "py" - 'Python2.7' - else - "Java" - end - elsif exec_path.blank? - "Java" - else - language - end - end - - def only_publish_game shixun, type - shixun_tomcat = Redmine::Configuration['shixun_tomcat'] - gameInfo = shixun.gameInfo - uri ="#{shixun_tomcat}/bridge/game/publishGame" - params = {:gameInfo => "#{gameInfo}"} - logger.info("%%%%%%%%%%%%params is #{params}") - res = uri_exec uri, params - if res && res['code'].to_i != 0 - raise("实训云平台繁忙(繁忙等级:90)") - end - end - - def publish_game_and_tpimodify myshixun, type - shixun_tomcat = Redmine::Configuration['shixun_tomcat'] - 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/resetTpiScript" - params = {:gameInfo => "#{gameInfo}"} - logger.info("%%%%%%%%%%%%params is #{params}") - res = uri_exec uri, params - if res && res['code'].to_i != 0 - raise("实训云平台繁忙(繁忙等级:98)") - end - end - - ## 若实训关卡位置,关卡数等信息发生变化则需要修改脚本内容 - def modify_shixun_script shixun, script - if script.present? - source_class_name = [] - challenge_program_name = [] - shixun.challenges.map(&:exec_path).each do |exec_path| - challenge_program_name << "\"#{exec_path}\"" - if shixun.mirror_name.try(:first) == "Java" - if exec_path.nil? || exec_path.split("src/")[1].nil? - source = "\"\"" - else - source = "\"#{exec_path.split("src/")[1].split(".java")[0]}\"" - end - source_class_name << source.gsub("/", ".") if source.present? - elsif shixun.mirror_name.try(:first) == "C#" - if exec_path.nil? || exec_path.split(".")[1].nil? - source = "\"\"" - else - source = "\"#{exec_path.split(".")[0]}.exe\"" - end - source_class_name << source if source.present? - end - end - script = if script.include?("sourceClassName") && script.include?("challengeProgramName") - script.gsub(/challengeProgramNames=\(.*\)/,"challengeProgramNames=\(#{challenge_program_name.reject(&:blank?).join(" ")}\)").gsub(/sourceClassNames=\(.*\)/, "sourceClassNames=\(#{source_class_name.reject(&:blank?).join(" ")}\)") - else - script.gsub(/challengeProgramNames=\(.*\)/,"challengeProgramNames=\(#{challenge_program_name.reject(&:blank?).join(" ")}\)").gsub(/sourceClassNames=\(.*\)/, "sourceClassNames=\(#{challenge_program_name.reject(&:blank?).join(" ")}\)") - end - end - return script - #shixun.update_column(:evaluate_script, script) - end - - # 若实训有更改,则修改已发不实训的标记为已更改 - # shixun_modifies表中1表示已更改,进入myshixun需要强制重置,0表示没有修改 - # type 0:表示已经是最新的了;1:表示已经有修改 - # res返回结果0表示正确,-1表示有异常 - def add_shixun_modify_status shixun, type - shixun_tomcat = Redmine::Configuration['shixun_tomcat'] - gameInfo = shixun.gameInfo - uri ="#{shixun_tomcat}/bridge/game/publishGame" - params = {:gameInfo => "#{gameInfo}"} - logger.info("%%%%%%%%%%%%params is #{params}") - res = uri_exec uri, params - if res && res['code'].to_i != 0 - raise("实训云平台繁忙(繁忙等级:90)") - end - end - - # 判断实训的路径、language是否更改,如果修改在TPI中需要重置脚本 - # 目前为止,container为challenge和game类型 - # 改工作必须在challenge或者game保存后执行 - # type 1:表示既需要提示又需要更新脚本的,0:表示仅仅需要提示 - def should_modify_myshixun_script shixun, type - if type == 1 - shixun.update_column(:reset_time, shixun.try(:updated_at)) - else - shixun.update_column(:modify_time, shixun.try(:updated_at)) - end - end - - def shixun_modify_status_publish shixun, type - shixun_tomcat = Redmine::Configuration['shixun_tomcat'] - # 更新测试集 - gameInfo = shixun.gameInfo - uri ="#{shixun_tomcat}/bridge/game/publishGame" - # 更新脚本 - tpiList =[] - myshixuns = shixun.myshixuns - if myshixuns.present? - myshixuns.each do |myshixun| - logger.info("tpiID is #{myshixun.id}") - tpiID = myshixun.id - instanceGitURL = gitlab_url myshixun - logger.info("instanceGitURL is #{instanceGitURL}") - tpiList << {:tpiID => tpiID, :instanceGitURL => instanceGitURL} - logger.info("###############{tpiList.to_json unless tpiList.blank?}") - end - end - tpiList = Base64.urlsafe_encode64(tpiList.to_json) unless tpiList.blank? - params = {:gameInfo => "#{gameInfo}", :tpiList => "#{tpiList}" } - logger.info("%%%%%%%%%%%%params is #{params}") - # end - res = uri_exec uri, params - if res && res['code'].to_i != 0 - raise("实训云平台繁忙(繁忙等级:90)") - end - end - - # 仅仅产生记录,用于已执行publish的方法 - # ShixunModify中status 1:表示有更改,开启实训的时候需要重置,0:表示不需要重置或已重置完成 - def shixun_modify_status_without_publish shixun, type - myshixuns = shixun.myshixuns - unless myshixuns.blank? - myshixuns.each do |myshixun| - shixun_modify = ShixunModify.where(:shixun_id => shixun.id, :myshixun_id => myshixun.id).first - if shixun_modify.nil? - ShixunModify.create!(:shixun_id => shixun.id, :myshixun_id => myshixun.id, :status => type) - else - shixun_modify.update_attributes!(:status => type) - end - end - end - end - - # 通关后,把最后一次成功的代码存到数据库 - # type 0 创始内容, 1 最新内容 - def game_passed_code game_id, path, myshixun_gpid, type - g = Gitlab.client - rev = rev.nil? ? "master" : rev - path = path.strip if path.present? - file_content = g.files(myshixun_gpid, path, rev).content - if file_content.blank? - # gitlab缺陷:forked完成,短暂时间内取不了内容的,所以做一个小轮询,间隔0.1秒 - # 超过2秒则失败,需通过页面刷新 - for i in 0..30 do - sleep(0.1) - file_content = g.files(myshixun_gpid, path, rev).content - unless file_content.blank? - break - end - end - end - unless file_content.present? - raise("获取文件代码异常") - end - file_content = tran_base64_decode64(file_content) - game_code = GameCode.where(:game_id => game_id, :path => path).first - if game_code.nil? - GameCode.create!(:game_id => game_id, :new_code => file_content, :path => path) - else - game_code.update_attributes!(:new_code => file_content) - end - end - - def game_code_init game_id, path - game_code = GameCode.where(:game_id => game_id, :path => path).first - GameCode.create(:game_id => game_id, :path => path) if game_code.blank? - end - - # 判断用户是否认证 - def check_authentication - # return true - # if params[:action] == "on_search" || params[:action] == "apply_trail" # 之所以这样处理是为了避开account页面ajax加载 - # return true - # end - Rails.logger.info("check_authentication start") - unless User.current.logged? - url = request.original_url - redirect_to signin_path(:back_url => url) - return - end -=begin - if User.current.created_on.strftime('%Y-%m-%d %H:%M:%S') > "2018-01-01 00:00:00" && User.current.phone.blank? - redirect_to change_or_bind_path(:type => "phone") - return - end -=end - user_e = UserExtensions.where(:user_id => User.current.id).first - if User.current.lastname.blank? || user_e.school_id.blank? || user_e.identity.blank? || User.current.mail.blank? - redirect_to user_info_path() - Rails.logger.info("check_authentication end") - return - elsif User.current.certification != 1 # 系统没有授权 - day_cer = UserDayCertification.where(:user_id => User.current.id).last - unless (Time.now.to_i - day_cer.try(:created_at).to_i) < 86400 - redirect_to my_account_path() - Rails.logger.info("check_authentication end") - return - end - end - end - - def match_specific_symbol(str) - str.gsub(" ", "").gsub(/\r\n$/, "").gsub("\r\n", "
").gsub(/\t/, "").html_safe - end - - # textarea 以/r/n开头时,回车效果会被替换,因此先把\r转换成\r 再添加一个\r(直接添加\r不行) - def match_specific_symbol1(str) - str.gsub(/\A\r/, "\r\r") - end - - # 积分表中建立记录行为,有过奖励则不重复奖励 - def reward_grade(user, container_id, container_type, score) - grade = Grade.where(:user_id => user.id, :container_id => container_id, :container_type => container_type).first - if grade.nil? - Grade.create!(:user_id => user.id, :container_id => container_id, :container_type => container_type, :score => score) - user.update_column(:grade, (score.to_i + user.grade.to_i)) - end - end - - def reward_experience(user, container_id, container_type, score) - experience = Experience.where(:user_id => user.id, :container_id => container_id, :container_type => container_type).first - if experience.nil? - Experience.create!(:user_id => user.id, :container_id => container_id, :container_type => container_type, :score => score) - user.update_column(:experience, (score.to_i + user.experience.to_i)) - end - end - - def shixun_name game_id - game = Game.where(:id => game_id).first - game.nil? ? "---" : game.challenge.shixun.name - end - - def grade_shixun_name shixun_id - shixun = Shixun.where(:id => shixun_id).first - shixun.nil? ? "---" : shixun.name - end - - def game_position game_id - game = Game.where(:id => game_id).first - game.nil? ? "---" : game.challenge.position - end - - def managements_navigation_bar_show menu_type, sub_type, grandchild_type={} - case menu_type - when 1 - case sub_type - when 1 then "统计总表" - when 2 then "数据变化报表" - end - when 2 - sub_type == 1 ? "课程列表" : (sub_type == 2? "课堂列表" : (sub_type == 3? "实训作业" : "项目列表")) - when 3 - case sub_type - when 1 - "实训列表" - when 2 - "实训配置列表" - when 3 - "已发布的实训" - when 4 - "已关闭的实训" - when 5 - "镜像管理" - when 6 - "学员实训列表" - when 7 - "镜像类别图片" - when 8 - "TPI实训列表" - when 9 - "TPI性能测试结果" - end - when 4 - case sub_type - when 1 - "实训课程列表" - when 2 - "实训课程配置" - when 3 - "已发布实训课程" - end - when 5 - case sub_type - when 1 - "竞赛列表" - end - when 6 - if sub_type == 1 - link_to('单位列表', departments_part_managements_path()) + "#{grandchild_type[:next_type] == 1 ? " > #{grandchild_type[:school].name}" : ""}" - elsif sub_type == 3 - "合作伙伴" - else - "单位部门列表" - end - when 7 - sub_type == 1 ? "用户列表" : (sub_type == 2 ? "试用授权列表" : "自动授权列表") - when 8 - sub_type == 1 ? "作业回复" : - (sub_type == 2 ? "实训反馈" : - (sub_type == 3 ? "讨论区" : "课堂讨论区") - ) - when 9 - sub_type == 1 ? "实训留言列表" : "" - when 10 - sub_type == 1 ? "实名认证" : - (sub_type == 2 ? "试用授权" : - (sub_type == 3 ? "部门审批" : - (sub_type == 4 ? "单位审批" : - (sub_type == 5 ? "实训发布" : - (sub_type == 6 ? "实训课程发布" : "职业认证") - ) - ) - ) - ) - when 11 - "工程认证+" - when 12 - sub_type == 1 ? "过关任务模板" : - (sub_type == 2 ? "实训简介模板" : - (sub_type == 3 ? "背景知识模板" : - (sub_type == 4 ? "通用评测模板" : - (sub_type == 5 ? "新课导语模板" : - (sub_type == 6 ? "实训评分设置" : - (sub_type == 7 ? "技术体系" : "升级通知") - ) - ) - ) - ) - ) - end - end - - - # codeMirror语言转换 - def language_switch language - case language - when "Java" - "text/x-java" - when "C" - "text/x-csrc" - when "C++" - "text/x-c++src" - when "Python" - "text/x-python" - when "Ruby" - "text/x-ruby" - end - end - - # 实训语言的种类 - def shixun_language - ["Java", "C", "C++", "Python2.7", "Python3.6", "MySQL/Java", "Html", "JFinal", "Docker", "Ethereum", "Dynamips", "MachineLearning", - "Verilog","Spark","MySQL/Python3.6","PHP","PHP/Web","Hadoop", "Golang","Android","Matlab","Shell", "Git", 'Perl6', 'Kotlin', 'Elixir', 'JavaScript', 'Ruby'] - end - - # 实训试用专业 - def shixun_major_option - content = [] - content << ["选择实训适用的专业", 0] - content << ["计算机科学与技术", 635] - content << ["软件工程", 636] - content << ["网络工程", 637] - content << ["信息安全", 638] - content << ["物联网工程", 639] - content << ["信息工程", 622] - content << ["通信工程", 619] - end - - # 实训面向学员 - def shixun_trainee - content = [] - content << ["初级学员", 1] - content << ["中级学员", 2] - content << ["高级学员", 3] - content << ["顶级学员", 4] - end - - # 班级设置排序中文 - def switch_to_chinese word - case word - when "boards" - result = "讨论区" - when "news" - result = "通知" - when "homework" - result = "作业" - when "exercises" - result = "试卷" - when "poll" - result = "问卷" - when "statistics" - result = "统计" - when "attachment" - result ="资源" - end - return result - end - - def allow_to_view_challenge challenge, shixun - # 判断对应关卡的game是否开启,如果开启则允许查看 - game_count = Game.where(:challenge_id => challenge, :user_id => User.current, :status => [0,1,2]).count - if game_count > 0 - return true - else - return false - end - end - - # 已通过的关卡数 - def had_passed_changllenge_count shixun, user - myshixun = Myshixun.where(:shixun_id => shixun.id, :user_id => user.id).first - if myshixun.nil? - 0 - elsif myshixun.games.select{|game| game.status == 2}.count == 0 - -1 - elsif myshixun.games.select{|game| game.status == 0}.count > 0 - [myshixun.games.select{|game| game.status == 2}.count + 1] - else - myshixun.games.select{|game| game.status == 2}.count - end - end - - # 判断TPM已通过的管卡数 - def had_passed_games_count shixun_id, user_id - #Game.find_by_sql("select count(*) as unpass_count from games where games.status=2 and user_id=#{user_id} and games.challenge_id in (select id from challenges where shixun_id=#{shixun_id})").first.try(:unpass_count) - Game.find_by_sql("SELECT count(*) cnt FROM `games` g join myshixuns m on m.id = g.myshixun_id where m.user_id = #{user_id} and m.shixun_id = #{shixun_id} and g.status = 2;").first.try(:cnt) - end - - # 用户实训评测状态 - def user_evaluate_status shixun, user - myshixun = shixun.myshixuns.where(:user_id => user.id).first - if myshixun.blank? - "--" - else - game_id = myshixun.games.map(&:id) - output = Output.where(:game_id => game_id).reorder("updated_at desc").first - if output.blank? - "--" - else - if output.try(:code) == -1 - time_from_now(output.updated_at).to_s + "评测失败" - else - time_from_now(output.updated_at).to_s + "评测成功" - end - end - end - end - - def student_work_performance score - case score - when (90..100) - '优秀' - when (70...90) - '良好' - when (60...70) - '及格' - when (0...60) - '不及格' - end - end - - # 已通过的关卡数 返回int类型(包含查看参考答案的) - def had_passed_changllenge_num myshixun - if myshixun.nil? - 0 - else - myshixun.games.select{|game| game.status == 2}.count - end - end - - # 已通过的关卡数 返回int类型(未查看参考答案) - def had_passed_no_ans_changllenge_num myshixun - if myshixun.nil? - 0 - else - myshixun.games.select{|game| game.status == 2 && game.final_score > 0}.count - end - end - - # TPI状态 :已通关、未通关、未开启 - def my_shixun_status shixun, user - status = "" - myshixun = Myshixun.where(:shixun_id => shixun.id, :user_id => user.id).first - if myshixun.nil? - status = "未开启" - else - status = myshixun.is_complete? ? "已通关" : "未通关" - end - status - end - - # 定义实训相关方法 - def sum_final_score - Game.find_by_sql("SELECT sum(final_score) as total_score FROM `games` where user_id=#{User.current.id}").first.try(:total_score) - end - - # 获取某个myshixun的得分 - def sum_myshixun_score myshixun_id - Game.find_by_sql("SELECT sum(final_score) as total_score FROM `games` where myshixun_id=#{myshixun_id}").first.try(:total_score) - end - - # myshixun 最高分 - def top_score shixun, position - Game.find_by_sql("SELECT max(final_score) as top_score FROM `games` g, `challenges` c where g.challenge_id = c.id and c.position=#{position} and g.myshixun_id in (SELECT id FROM `myshixuns` ms where ms.shixun_id=#{shixun.id})").first.try(:top_score) - end - - # 实训平均分 - def shixun_avg_score shixun, position - Game.find_by_sql("SELECT avg(g.final_score) as avg_score FROM `games` g, `challenges` c where g.challenge_id=c.id and c.position=#{position} and g.myshixun_id in (SELECT id FROM `myshixuns` ms where ms.shixun_id=#{shixun.id})").first.try(:avg_score) - end - - # 正在进行中任务 - def shixun_running shixun, position - Shixun.find_by_sql("SELECT count(*) as count FROM `myshixuns` ms, `games` g, `challenges` c where g.myshixun_id = ms.id and ms.shixun_id =#{shixun.id} and g.challenge_id=c.id and c.position=#{position} and g.status in ('0','1');").first.try(:count) - end - - # 已完成任务 - def shixun_done shixun, position - Shixun.find_by_sql("SELECT count(*) as count FROM `myshixuns` ms, `games` g, `challenges` c where g.myshixun_id = ms.id and ms.shixun_id =#{shixun.id} and g.challenge_id=c.id and c.position=#{position} and g.status=2;").first.try(:count) - end - - # 测评次数 - def shixun_exec_total_count shixun, position - Game.find_by_sql("SELECT * FROM `outputs` op, `games` g, `myshixuns` m where op.game_id = g.id and g.stage='#{position}' and m.parent_id = '#{shixun.id}';") - end - - # 平均耗时 - def game_avg_day created_at, updated_at - time = (updated_at - created_at).to_i - day = time / 86400 - end - - # 平均耗时 - def game_avg_hour created_at, updated_at - time = (updated_at - created_at).to_i - hour = time % (24*60*60) / (60*60) - end - - # 平均耗时 - def game_avg_min created_at, updated_at - time = (updated_at - created_at).to_i - min = time % (24*60*60) % (60*60) / 60 - end - - # 耗时:天、小时、分、秒 - # 小于1分钟则不显示 - def game_spend_time time - day = time / 86400 - hour = time % (24*60*60) / (60*60) - min = time % (24*60*60) % (60*60) / 60 - sec = time % (24*60*60) % (60*60) % 60 - if day < 1 - if hour < 1 - if min < 1 - if sec < 1 - time = "--" - else - time = "#{sec}秒" - end - else - time = "#{min}分钟 #{sec}秒" - end - else - time = "#{hour}小时 #{min}分钟 #{sec}秒" - end - else - time = "#{day}天 #{hour}小时 #{min}分钟 #{sec}秒" - end - return time - end - - # 耗时:天、小时、分 - # 小于1分钟则不显示 - def work_spend_time time - if time == 0 - time = "0小时" - else - day = time / 86400 - hour = time % (24*60*60) / (60*60) - min = (time % (24*60*60) % (60*60) / 60.0).ceil - if day < 1 - if hour < 1 - if min < 1 - time = "1分" - else - time = "#{min}分" - end - else - time = "#{hour}小时#{min}分" - end - else - time = "#{day}天#{hour}小时#{min}分" - end - end - return time - end - - # 耗时:小时、分、秒 00:00:00 - # 小于1秒钟则不显示 - def com_spend_time time - hour = time / (60*60) - min = time % (60*60) / 60 - sec = time % (60*60) % 60 - hour_str = "00" - min_str = "00" - sec_str = "00" - if hour >= 1 && hour < 10 - hour_str = "0#{hour}" - elsif hour >= 10 - hour_str = "#{hour}" - end - - if min >= 1 && min < 10 - min_str = "0#{min}" - elsif min >= 10 - min_str = "#{min}" - end - - if sec >= 1 && sec < 10 - sec_str = "0#{sec}" - elsif sec >= 10 - sec_str = "#{sec}" - end - - time = "#{hour_str} : #{min_str} : #{sec_str}" - return time - end - - def consume_time time - time.strftime('%Y/%m/%d %H:%M:%S') - end - - def avg_spend_time shixun_id, position - Game.find_by_sql("SELECT avg(g.end_time - g.open_time) as avg_time FROM `games` g, `challenges` c where c.id=g.challenge_id and g.status =2 and c.position = #{position} and g.myshixun_id in (SELECT id FROM `myshixuns` where shixun_id= #{shixun_id});").first.try(:avg_time).to_i - end - - # 已闯关 - def had_pass shixun_id, position - Game.find_by_sql("SELECT count(*) as count FROM `games` g, `challenges` c where c.id=g.challenge_id and g.status =2 and c.position =#{position} and g.myshixun_id in (SELECT id FROM `myshixuns` where shixun_id=#{shixun_id});").first.try(:count) - end - - # 单个game测评次数 - def avg_my_pass game - Output.where(:game_id => game).count - end - - def shixun_final_score myshixun - Game.find_by_sql("SELECT sum(final_score) as final_score FROM `games` where myshixun_id='#{myshixun.id}';").first.try(:final_score) - end - - # def user_blogs_path(resource,parameters={}) - # super - # end - # 复制一个任务 - def publish_games challenge, myshixun_id, index - game = Game.new - game.attributes = challenge.attributes.dup.except("id","shixun_id","user_id","visits") - game.myshixun_id = myshixun_id - game.user_id = User.current.id - game.stage = challenge.position - index == 0 ? game.status = 0 : game.status = 3 - challenge_samples = challenge.challenge_samples - test_sets = challenge.test_sets - if game.save - unless challenge_samples.blank? - challenge_samples.each do |cs| - ChallengeSample.create(:game_id => game.id, :input => cs.input, :output => cs.output, :challenge_id => -1) - end - end - unless test_sets.blank? - test_sets.each do |ts| - TestSet.create(:game_id => game.id, :input => ts.input, :output => ts.output, :challenge_id => -1) - end - end - end - end - - def git_repository_url project, type - if type == "Shixun" - rep_identify = Repository.where(:shixun_id => project.id, :type => "Repository::Gitlab").first.try(:identifier) - elsif type == "Myshixun" - rep_identify = Repository.where(:myshixun_id => project.id, :type => "Repository::Gitlab").first.try(:identifier) - else - rep_identify = Repository.where(:project_id => project.id, :type => "Repository::Gitlab").first.try(:identifier) - end - gitlab_address = Redmine::Configuration['gitlab_address'] - gitUrl = gitlab_address.to_s+"/"+project.owner.to_s+"/"+ rep_identify + "."+"git" - end - - def gitlab_url container - g = Gitlab.client - url = "#{Redmine::Configuration['gitlab_address_ip']}/#{g.project(container.try(:gpid)).try(:path_with_namespace)}.git" - end - - def gitlab_address_url container - g = Gitlab.client - url = "#{Redmine::Configuration['gitlab_address']}/#{g.project(container.try(:gpid)).try(:path_with_namespace)}.git" - end - - # paranet_gpid 为fork的源头 - # u_gid 为当前用户在gitlab中对应的用户id - def sync_gitlab_rep container, parent_gpid, u_gid - Rails.logger.info("# sync_gitlab_rep # parent_gpid is #{parent_gpid}, u_gid is #{u_gid}") - if container.class == Myshixun - gshixun = Gitlab.client.fork(parent_gpid, u_gid) - container.update_attribute(:gpid, gshixun.id) - end - return gshixun.try(:id) - end - - # def git_shixun_url shixun, login - # rep_identify = Repository.where(:shixun_id => shixun.id, :type => "Repository::Gitlab").first.try(:identifier) - # gitlab_address = Redmine::Configuration['gitlab_address'] - # gitUrl = gitlab_address.to_s+"/"+login+"/"+ rep_identify + "."+"git" - # end - - # def git_shixun_url_ip shixun, login - # rep_identify = Repository.where(:shixun_id => shixun.id, :type => "Repository::Gitlab").first.try(:identifier) - # gitlab_address = Redmine::Configuration['gitlab_address_ip'] - # gitUrl = gitlab_address.to_s+"/"+login+"/"+ rep_identify + "."+"git" - # end - - # def git_myshixun_url_ip myshixun, user_id - # g = Gitlab.client - # login = User.where(:id => user_id).first.try(:login) - # rep_identify = g.project(myshixun.gpid).try(:name) - # gitlab_address = Redmine::Configuration['gitlab_address_ip'] - # gitUrl = gitlab_address.to_s+"/"+login+"/"+ rep_identify + "."+"git" - # end - - # myshixun git url by domain - # def git_myshixun_url myshixun, user_id - # g = Gitlab.client - # login = User.where(:id => user_id).first.try(:login) - # rep_identify = g.project(myshixun.gpid).try(:name) - # gitlab_address = Redmine::Configuration['gitlab_address'] - # gitUrl = gitlab_address.to_s+"/"+login+"/"+ rep_identify + "."+"git" - # end - - def uri_exec uri, params - begin - Rails.logger.info("@parmas is #{params}, url is #{uri}") - uri = URI.parse(URI.encode(uri.strip)) - res = Net::HTTP.post_form(uri, params).body - res = JSON.parse(res) - rescue => e - Rails.logger.error("failed to post data to brige! #{e}") - raise("实训云平台繁忙(繁忙等级:84)") - end - end - - # type 为繁忙等级 - # status-> 501:check检查版本库是否有代码异常 - # status-> 502:实训评测异常;503实训版本库check异常 - def interface_post uri, params, status - begin - uri = URI.parse(URI.encode(uri.strip)) - res = Net::HTTP.post_form(uri, params).body - res = JSON.parse(res) - if (res && res['code'] != 0) - raise(status) - end - res - rescue Exception => e - Rails.logger.error("post failed! #{e}") - raise("实训云平台繁忙(繁忙等级:#{status})") - end - end - - def get_url_exec uri, options={} - begin - uri = URI.parse(URI.encode(uri.strip)) - res = Net::HTTP.get_response(uri).body - res = JSON.parse(res) - rescue => e - logger.error("get response failed ! #{e}") - raise("实训云平台繁忙(繁忙等级:84)") - end - end - - def uri_json_exec uri, params - Net::HTTP.start(uri.hostname, uri.port) {|http| - http.post(uri.path, params.to_json) - } - - http = Net::HTTP.new(uri.host, uri.port) - res = Net::HTTP.post(uri, params.to_json).body - res = JSON.parse(res) - end - - def last_reply_time container_id - message = Message.where(:root_id => container_id).order("created_on desc").first - time = message.created_on - return time - end - - def judge_Chinese_num str - cn_reg = /[\u4e00-\u9fa5]{1}/ - cn_number = str.scan(cn_reg).size - en_number = str.size - cn_number - size = 1.9* cn_number + en_number - end - - # homework_common状态 - # 0:挂起;1:提交中;2:匿评中;3:评阅中 - def new_homework_common_status status - case status - when 0 - "未发布" - when 1 - "提交中" - when 2 - "补交中" - when 3 - "匿评中" - when 4 - "申诉中" - when 5 - "评阅中" - when 6 - "已结束" - end - end - - # 作业不同状态的不同样式 - def homework_status_color status - style = "" - case status - when '未发布' - style = 'edu-filter-btn-no-late' - when '提交中', '评阅中', '匿评中', '交叉评阅中' - style = 'edu-filter-btn-orange' - when '已开启补交' - style = 'edu-filter-btn-green' - when '已截止', '未开启补交' - style = 'edu-filter-btn-red' - when '已结束' - style = 'edu-filter-btn-end' - when '申诉中' - style = 'edu-filter-btn-appeal' - end - end - - # 有分班权限的课堂 学生提交作品时发送的消息对象 - def tiding_teachers course, member - if course.teacher_course_groups.count > 0 - member_ids = course.teacher_course_groups.where(:course_group_id => member.try(:course_group_id)).pluck(:member_id) - - teachers = course.teachers.where("members.id not in (#{course.teacher_course_groups.pluck(:member_id).size > 0 ? course.teacher_course_groups.pluck(:member_id).join(',') : -1}) or - members.id in (#{member_ids.size > 0 ? member_ids.join(',') : -1})") - else - teachers = course.teachers - end - teachers - end - - # 分班管理的老师所看到的成员数 - def group_student_count course - member = @course.members.where(:user_id => User.current.id).first - if User.current.allowed_to?(:as_teacher, course) && member.present? && member.teacher_course_groups.count > 0 - student_count = course.members.where(:course_group_id => member.teacher_course_groups.pluck(:course_group_id)).select{|member| member.roles.to_s.include?("Student")}.count - else - student_count = course.student.count - end - student_count - end - - # 已提交作品 - def late_commit_work_status work, homework - if homework.allow_late - link_to "补交附件", student_work_path(work, :is_focus => 1), :class => 'edu-filter-btn edu-activity-orange ml15 fl mt5', :title => "可追加作品修订附件" - else - "未开启补交".html_safe - end - end - - # 未提交作品 - def un_commit_work_status project, homework - if homework.allow_late - if homework.homework_type == 3 && project.nil? && homework.homework_detail_group.base_on_project == 1 - link_to "补交作品", "javascript:void(0)", :class => 'edu-filter-btn edu-activity-orange ml15 fl mt5', :style => "cursor:not-allowed", :title => '请先关联项目再补交作品' - else - link_to "补交作品", new_student_work_url_without_domain(homework.id), :class => 'edu-filter-btn edu-activity-orange ml15 fl mt5' - end - else - "未开启补交".html_safe - end - end - - # 判断作业有多少人提交了 - # - def had_commit_studentwork_count homework_common - member = homework_common.course.members.where(:user_id => User.current.id).first - student_works = homework_common.student_works - if member.present? && member.teacher_course_groups.count > 0 - group_students = homework_common.course.members.where(:course_group_id => member.teacher_course_groups.pluck(:course_group_id)).map(&:user_id) - student_works = student_works.where(:user_id => group_students) - end - student_works.where("work_status !=?", 0).count - end - - # 实训作业的有效作品数 - def effective_shixun_work_count homework_common - count = 0 - shixun = homework_common.shixuns - if shixun - homework_common.student_works.where("work_status !=?", 0).each do |work| - myshixun = work.myshixun - count = count + (myshixun && myshixun.games.select{|game| game.status == 2}.size > 0 ? 1 : 0) - end - end - count - end - - # 实训作业的通关作品数 - def tongguan_shixun_work_count homework_common - count = 0 - shixun = homework_common.shixuns.first - if shixun - challenge_count = shixun.challenges.count - homework_common.student_works.where("work_status !=?", 0).each do |work| - myshixun = work.myshixun - if myshixun && myshixun.games.select{|game| game.status == 2}.size == challenge_count - count = count + 1 - end - end - end - count - end - - # 未提交作品数统计 - def had_uncommit_studentwork_count homework_common - member = homework_common.course.members.where(:user_id => User.current.id).first - student_works = homework_common.student_works - if member.present? && member.teacher_course_groups.count > 0 - group_students = homework_common.course.members.where(:course_group_id => member.teacher_course_groups.pluck(:course_group_id)).map(&:user_id) - student_works = student_works.where(:user_id => group_students) - end - student_works.where("work_status =?", 0).count - end - - # 未评阅 - def had_unevaluate_count homework_common - #count = StudentWorksScore.find_by_sql("SELECT count(distinct student_work_id) as count FROM student_works_scores sws, student_works sw, homework_commons hc where hc.id =#{homework_common.id} and sw.homework_common_id=hc.id and sw.is_delete = 0 and sws.student_work_id = sw.id and sws.user_id=#{User.current.id};").first.try(:count).to_i - member = homework_common.course.members.where(:user_id => User.current.id).first - student_works = homework_common.student_works - if member.present? && member.teacher_course_groups.count > 0 - group_students = homework_common.course.members.where(:course_group_id => member.teacher_course_groups.pluck(:course_group_id)).map(&:user_id) - student_works = student_works.where(:user_id => group_students) - end - has_comment = StudentWorksScore.where(:student_work_id => student_works.map(&:id), :reviewer_role => [1, 2]).group_by(&:student_work_id).count - student_count = student_works.count - return student_count - has_comment - end - - # 该阶段还有多长时间结束/距下一阶段还有多长时间 - def homework_curr_time homework_common - result = {} - status = "" - time = "" - if homework_common.course.try(:is_end) - status = "已结束" - time = format_date homework_common.course.end_date - else - ho_detail_manual = homework_common.homework_detail_manual - if ho_detail_manual - case ho_detail_manual.comment_status - when 0 - status = "未发布" - when 1 - if homework_common.end_time && homework_common.end_time >= Time.now - status = "提交中" - time = how_much_time(homework_common.end_time) - end - when 3 - if ho_detail_manual.evaluation_end && ho_detail_manual.evaluation_end > Time.now - status = "匿评中" - time = how_much_time(ho_detail_manual.evaluation_end) - end - when 4 - if ho_detail_manual.appeal_time && ho_detail_manual.appeal_time > Time.now - status = "申诉中" - time = how_much_time(ho_detail_manual.appeal_time) - end - when 5 - status = "评阅中" - when 6 - status = "评阅中" - end - end - end - result[:status] = status - result[:time] = time - result - end - - # 试卷:该阶段还有多长时间结束/距下一阶段还有多长时间 - def exercise_curr_time exercise - result = {} - status = "" - time = "" - case exercise.exercise_status - when 1 - status = "未发布" - when 2 - if exercise.end_time && exercise.end_time >= Time.now - status = "提交中" - time = how_much_time(exercise.end_time) - end - when 3 - status = "已截止" - time = format_time exercise.end_time - end - result[:status] = status - result[:time] = time - result - end - - # 问卷:该阶段还有多长时间结束/距下一阶段还有多长时间 - def poll_curr_time poll - result = {} - status = "" - time = "" - case poll.polls_status - when 1 - status = "未发布" - when 2 - if poll.end_time && poll.end_time >= Time.now - status = "提交中" - time = how_much_time(poll.end_time) - end - when 3 - status = "已截止" - time = format_time poll.end_time - end - result[:status] = status - result[:time] = time - result - end - - # 公共分页 - def paginator_list objs, objs_count, limit, is_remote - @is_remote = is_remote - @objs_count = objs.count - @obj_pages = Paginator.new @objs_count, limit, params['page'] || 1 - @offset ||= @obj_pages.offset - @objs = paginateHelper @attachments,25 - end - - # 判断当前用户能否对消息进行操作 - def allow_to_show applied_message - (User.current.id == applied_message.user_id && applied_message.status == 0) ? true : false - end - - # 获取竞赛的管理人员 - def contest_managers contest - contest.contest_members.select{|cm| cm.roles.to_s.include?("ContestManager")} - end - - # 获取竞赛的评委人员 - def contest_judges contest - contest.contest_members.select{|cm| cm.roles.to_s.include?("Judge")} - end - - # 获取竞赛的参赛人员 - def contest_contestants contest - contest.contest_members.select{|cm| cm.roles.to_s.include?("Contestant")} - end - - # 字符串加密 - def aes_encrypt(key, encrypted_string) - aes = OpenSSL::Cipher::Cipher.new("AES-128-ECB") - aes.encrypt - aes.key = key - txt = aes.update(encrypted_string) << aes.final - txt.unpack('H*')[0].upcase - end - - # 字符串解密 - def aes_dicrypt(key, dicrypted_string) - aes = OpenSSL::Cipher::Cipher.new("AES-128-ECB") - aes.decrypt - aes.key = key - aes.update([dicrypted_string].pack('H*')) << aes.final - end - # 获取多种类型的user用户名 - def user_message_username user - user.try(:show_name) - end - - # 超出1w后用k+形式显示 - def switch_integer_into_k number - number > 10000 ? (number.to_f / 1000).round.to_s + "k" : number - end - - # 判断某个课程是否包含仅对自己可见的作业 - def course_has_score_open_common_homework course - course.homework_commons.select{|hc| hc.score_open == 0}.count > 0 ? true : false - end - - def welcome_course_message_count course_id - board_id = Board.where(:course_id => course_id).first.try(:id) - message_count = Message.where(:board_id => board_id).count - return message_count - end - - # 可以查看到资源库的资源 - def welcome_course_file_count course - course.attachments.count - end - - # 超级管理员实训评分设置的横轴 - def shixun_quality_show quality - lower = quality.lower_limit - upper = quality.upper_limit - result = "#{quality.name}" - if lower.present? && upper.present? - result = if(lower > lower.round) - "#{result}(#{lower.round}," - else - "#{result}[#{lower.round}," - end - - result = if(upper >= upper.round) - "#{result}#{upper.round}]" - else - "#{result}#{upper.round})" - end - end - return result - end - - # 管理员实训评分中 "指标"与"标准"的对应 - def description_of_quality indicator, position - indicator.score_quality_descriptions.where(:position => position).first.try(:name) if indicator.present? - end - - # 获取目录下所有文件,返回一个文件名的数组 type是查看文件的类型image表示图片 - # type [[1, "图片"], [2, "apk/exe"], [3, "txt"], [4, "html"]] - def get_dir_filename path, type, game_id - answer_picture = [] - image = ["png", "jpg", "gif", "jpeg", "bmp", "pic"] - if File.directory? path - Dir.foreach(path) do |file| - if file !="." and file !=".." - extension = file.split(".")[1].try(:downcase) - if image.include?(extension) && type == 1 - answer_picture << file - @type = "image" - elsif extension == "html" && type == 4 - answer_picture << file - @type = "html" - elsif extension == "txt" && type == 3 - answer_picture << file - @contents = "" - f = File.open("#{path}/#{file}", "r") - # ... process the file - f.each_line do |line| - if line.include?("Your score") - game = Game.find(game_id) - max_query_index = game.query_index - 1 - a = line[11, line.length-1].try(:strip) - outputs = game.outputs.where(:query_index => max_query_index) - outputs.update_all(:text_scor => a) if outputs.present? - end - @contents += "#{line}" - end - f.close - @type = "txt" - end - end - end - end - return answer_picture - end - - # 隐藏项目以外的信息 - # return: true 显示,false 不显示 - def hidden_unproject_infos - hidden_info = Setting.find_by_name("hidden_non_project") - (hidden_info && hidden_info.value == "1") ? true : false - end - - # 获取当前用户的fork数量 - def get_fork_from_project forked_from_project_id - Project.find(forked_from_project_id) - end - - # 判断当前用户是否已经fork过当前项目 - # project: current_project - def has_forked_cur_project project - cur_user_projects = Project.where(:user_id => User.current.id) - if cur_user_projects.count == 0 - false - else - has_forked = cur_user_projects.select{|cur_user_project| cur_user_project.forked_from_project_id == project.id} - has_forked.length > 0 ? true : false - end - end - - # 判断当前用户是否已经实训过当前项目 - # project: current_project - def has_exec_cur_shixun shixun - Myshixun.where(:user_id => User.current.id, :shixun_id => shixun.id).count > 0 ? true : false - end - - # 用户必须登录;必须创建了关卡;有实践任务的必须提交了版本库代码 - def allow_shixun_exec shixun - g = Gitlab.client - result = User.current.logged? && shixun.challenges.count > 0 - if shixun.challenges.where(:st => 0).count > 0 - result = result && g.trees(shixun.gpid).count.to_i > 0 - end - result - end - - # 判断当前用户是否可以开始实战 - def link_to_shixun_exec myshixun, shixun, str - is_modify = ShixunModify.where(:myshixun_id => myshixun.try(:id), :shixun_id => shixun.try(:id), :status => 1).first.blank? - if User.current.mail.blank? - link_to str, "javascript:void(0);", :onclick => "notice_box_redirect('#{security_settings_path}', '开启实训,请先绑定邮箱')", :class => "fr shixun-task-btn task-btn-orange mr15", :target => "_blank" - else - if is_modify || myshixun.blank? - link_to str, shixun_exec_shixun_path(shixun), :class => "fr shixun-task-btn task-btn-orange mr15", :target => "_blank" - else - link_to str, "javascript:void(0);", :onclick => "sure_box_redirect('#{myshixun_reset_myshixun_path(myshixun)}', '实训已经更新啦,系统正在为您重置')", :class => "fr shixun-task-btn task-btn-orange mr15" - end - end - end - - # 通过系统外部邮箱查找用户,如果用户不存在则用邮箱替换 - def get_user_by_mail mail - user = User.find_by_mail(mail) - user.nil? ? User.find(2) : user - end - - # 通过登录名查找用户,能查到返回用户姓名,否则返回登录名 - def link_to_user_login login, css_class - user = User.find_by_login(login) - user = user.nil? ? login : user - if user.is_a?(User) - name = user.show_name - link_to name, {:controller=> 'users', :action => 'show', id: user.id}, :class => css_class, :target => "_blank" - else - "#{h(user.to_s)}".html_safe - end - end - - def link_to_user_mail(mail, css_class) - user = User.find_by_mail(mail) - user = user.nil? ? mail : user - if user.is_a?(User) - name = user.show_name - link_to name, {:controller=> 'users', :action => 'show', id: user.id}, :class => css_class, :target => "_blank" - else - "#{h(user.to_s)}".html_safe - end - end - - # 通过系统外部用户名查找用户,如果用户不存在则用邮箱替换 - def get_user_by_login_and login - user = User.find_by_login(login) - (user.nil? || login == "root") ? User.find(2) : user - end - - # 登录名来自外部系统 - # 通过登录名查找用户,如果用户存在则显示用户姓名,否则显示登录名 - def get_user_by_login login - user = User.find_by_login(login) - user.nil? ? login : user.show_name - end - - # 重置user_path,目的是将id转换成用户名 - def user_path(resource, parameters = {}) - if Fixnum === resource - resource = User.find(resource) - end - super - end - - # 重置user_path,目的是将id转换成用户名 - # def shixun_path(resource, parameters = {}) - # if Fixnum === resource - # resource = Shixun.find(resource) - # end - # super - # end - - # 历史数据(老版本库数据)处理完则可以修改该放放 - def get_rep_identifier_by_project project - identifier = Repository.where(:project_id => project.id, :type => "Repository::Gitlab").first.try(:identifier) - result = identifier.nil? ? Repository.where(:project_id => project.id).first.try(:identifier) : identifier - result - end - - # 项目版本库导出Excel功能 - def export_rep_xls(gpid, options = {}) - g = Gitlab.client - cycle = params[:cycle] - rev = params[:rev] - if cycle == "week" - statics = g.rep_stats_week(gpid, :rev => rev) - elsif cycle == "month" - statics = g.rep_stats_month(gpid, :rev => rev) - end - xls_report = StringIO.new - book = Spreadsheet::Workbook.new - sheet1 = book.create_worksheet :name => l(:project_module_repository) - blue = Spreadsheet::Format.new :color => :blue, :weight => :bold, :size => 10 - sheet1.row(0).default_format = blue - sheet1.row(0).concat([l(:rep_branch),l(:rep_author),l(:rep_changeset),l(:rep_code_add),l(:rep_code_delete),l(:rep_code_modified),l(:rep_sode_time),l(:rep_sode_cycle),l(:rep_author_mail)]) - count_row = 1 - statics.each do |static| - user = User.where(:mail => static.email).first - sheet1[count_row,0] = rev - sheet1[count_row,1] = user.nil? ? static.uname : user.show_name - sheet1[count_row,2] = static.commits_num - sheet1[count_row,3] = static.add - sheet1[count_row,4] = static.del - sheet1[count_row,5] = static.changes - sheet1[count_row,6] = Time.now.strftime('%Y-%m-%d %H:%M:%S') - sheet1[count_row,7] = cycle == "week" ? "最近1周" : "最近一月" - sheet1[count_row,8] = static.email - count_row += 1 - end - book.write xls_report - xls_report.string - end - - # 项目issue列表导出Excel功能 - def issue_list_xls issues - xls_report = StringIO.new - book = Spreadsheet::Workbook.new - sheet1 = book.create_worksheet :name => "issues" - blue = Spreadsheet::Format.new :color => :blue, :weight => :bold, :size => 10 - sheet1.row(0).default_format = blue - sheet1.row(0).concat([l(:issue_xls_id),l(:issue_xls_tracker_id),l(:issue_xls_title),l(:issue_xls_description),l(:issue_xls_status),l(:issue_xls_assign),l(:issue_xls_priority),l(:issue_xls_author),l(:issue_xls_created_at),l(:milestone),l(:issue_xls_start),l(:issue_xls_due),l(:issue_xls_ratio)]) - count_row = 1 - issues.each do |issue| - sheet1[count_row,0] = issue.id - sheet1[count_row,1] = issue_tracker_change(issue.tracker_id) - sheet1[count_row,2] = issue.subject - sheet1[count_row,3] = (issue.description.gsub(/<\/?.*?>/,"")).html_safe - sheet1[count_row,4] = issue_status_change(issue.status_id) - sheet1[count_row,5] = issue.assigned_to.try(:show_name) - sheet1[count_row,6] = issue_priority_change(issue.priority_id) - sheet1[count_row,7] = issue.author.show_name - sheet1[count_row,8] = issue.created_on.nil? ? issue.created_on : issue.created_on.strftime('%Y-%m-%d %H:%M:%S') - sheet1[count_row,9] = issue.fixed_version.try(:name) - sheet1[count_row,10] = issue.start_date.nil? ? issue.start_date : issue.start_date.strftime('%Y-%m-%d') - sheet1[count_row,11] = issue.due_date.nil? ? issue.due_date : issue.due_date.strftime('%Y-%m-%d') - sheet1[count_row,12] = issue_ratio_change(issue.done_ratio, issue.status_id) - count_row += 1 - end - book.write xls_report - xls_report.string - end - - # 用户资料是否完善 - def user_data_complete user - user_extension = UserExtensions.where(:user_id => user.id).first - data = true - if user_extension.gender.nil? || user_extension.school_id.nil? || user.lastname.blank? || (user_extension.identity == 3 && user_extension.school_id.nil?) - data = false - end - return data - end - - # 获取用户单位 - # 优先获取高校信息,如果改信息不存在则获取occupation - def get_occupation_from_user user - School.where("id=?",user.user_extensions.school_id).first.try(:name).nil? ? user.user_extensions.try(:occupation) : School.where("id=?",user.user_extensions.school_id).first.try(:name) - end - - def update_visiti_count container - container.update_column(:visits, container.visits + 1) - end - - def if_hidden_subdomain field - domains = field.sub_domains.select{|domain| domain.hide.to_i == 0} - result = domains.length > 0 ? true : false - return result - end - - # 判断某个资源是否可以申请 - def attach_show_allow attach_id - attachment = Attachment.find(attach_id) - case attachment.container_type - when "Project" - User.current.member_of?(attachment.container) ? true : false - when "Course" - User.current.member_of_course?(attachment.container) ? true : false - when "OrgSubfield" - User.current.member_of_org?(attachment.container.organization) ? true : false - when "Principal" - User.current.id == attachment.author_id ? true : false - end - end - - # 判断某个私有资源是否可以发送下载权限 - # 结果为true不能下载,false可以下载 - def private_attachment_allow attachment_id - attach = Attachment.find(attachment_id) - # 条件取否,result结果为true则不能下载 - result = attach.is_public == 0 && attach.author != User.current && !attach.get_apply_resource_status(attach.id, User.current.id) && !attach_show_allow(attach) - end - - # Time 2015-03-24 15:27:29 - # Author lizanle - # Description 从硬盘上删除对应的资源文件 - def delete_kindeditor_assets_from_disk owner_id,owner_type - assets = Kindeditor::Asset.where(["owner_id = ? and owner_type = ?",owner_id,owner_type]) - if !assets.nil? && !assets.blank? - assets.all.each do |asset| - next if asset.nil? - filepath = File.join(Rails.root,"public","files","uploads", - asset[:created_at].to_s.gsub("+0800","").to_datetime.strftime("%Y%m").to_s, - asset[:asset].to_s) - File.delete(filepath) if File.exist?filepath - end - end - end - - def link_to_user_version(version, options = {}) - return '' unless version && version.is_a?(Version) - link_to_if version.visible?, format_version_name(version), { :controller => 'versions', :action => 'show', :id => version }, :class => "linkBlue" - end - - # 判断课程是否为精品课程 - def is_excellent_course course - (course.is_excellent? or course.excellent_option?) ? true : false - end - - # 判断课程对成员是否可见 - def visible_course?(course) - (course.is_delete? or (!course.is_public? && !User.current.member_of_course?(course))) ? false : true - end - - # 获取项目/课程总分 - # 发布缺陷 4分 回复缺陷 1分 提交一次 4分 讨论帖子 2分 回复帖子 1分 发布新闻 1分 - def static_project_score obj - score = obj.issue_num * 4 + obj.issue_journal_num + (obj.changeset_num||0) * 4 + obj.board_num * 2 + obj.board_message_num + obj.attach_num * 5 - end - - # 获取组织成员中文名字 - def get_org_member_role_name member - unless member.roles[0].nil? - case member.roles[0].name - when 'orgManager' - '管理人员' - when 'orgMember' - '组织成员' - end - end - end - - # 判断组织左侧展开或者隐藏 - def is_hide_org_left obj - if obj.nil? - return true - else - if obj.hide == 0 - return true - else - return false - end - end - end - - # Time 2015-03-24 16:38:05 - # Author lizanle - # Description after save后需要进行资源记录的更新 - # owner_type = 1 对应的是 memo - # owner_type = 2 对应的是forum - # owner_type = 3 对应的是message - # owner_type = 4 对应的是news - # owner_type = 5 对应的是comment - def update_kindeditor_assets_owner ids,owner_id,owner_type - ids.each do |id| - asset = Kindeditor::Asset.find(id.to_i) - asset.owner_id = owner_id - asset.owner_type = owner_type - asset.save - end - end - - # 更新课程活跃度得分 - def course_member_score(course_id,user_id,type) - course_contributor_score = CourseContributorScore.where("course_id =? and user_id =?", course_id, user_id).first - case type - when "HomeworkCommon" - if course_contributor_score.nil? - CourseContributorScore.create(:course_id => course_id, :user_id => user_id, :homework_journal_num => 1) - else - score = course_contributor_score.homework_journal_num.to_i + 1 - course_contributor_score.update_column(:homework_journal_num, score) - end - # 课程留言 - when "Course" - if course_contributor_score.nil? - CourseContributorScore.create(:course_id => course_id, :user_id => user_id, :journal_num => 1) - else - score = course_contributor_score.journal_num.to_i + 1 - course_contributor_score.update_column(:journal_num, score) - end - when "Message" - if course_contributor_score.nil? - CourseContributorScore.create(:course_id => course_id, :user_id => user_id, :message_num => 1) - else - score = course_contributor_score.message_num.to_i + 1 - course_contributor_score.update_column(:message_num, score) - end - when "MessageReply" - if course_contributor_score.nil? - CourseContributorScore.create(:course_id => course_id, :user_id => user_id, :message_reply_num => 1) - else - score = course_contributor_score.message_reply_num.to_i + 1 - course_contributor_score.update_column(:message_reply_num, score) - end - when "NewReply" - if course_contributor_score.nil? - CourseContributorScore.create(:course_id => course_id, :user_id => user_id, :news_reply_num => 1) - else - score = course_contributor_score.news_reply_num.to_i + 1 - course_contributor_score.update_column(:news_reply_num, score) - end - when "News" - if course_contributor_score.nil? - CourseContributorScore.create(:course_id => course_id, :user_id => user_id, :news_num => 1) - else - score = course_contributor_score.news_num.to_i + 1 - course_contributor_score.update_column(:news_num, score) - end - when "Attachment" - if course_contributor_score.nil? - CourseContributorScore.create(:course_id => course_id, :user_id => user_id, :resource_num => 1) - else - score = course_contributor_score.resource_num.to_i + 1 - course_contributor_score.update_column(:resource_num, score) - end - end - end - - # 删除某条记录相应减少课程统计数 - def down_course_score_num (course_id,user_id,type) - course_contributor_score = CourseContributorScore.where("course_id =? and user_id =?", course_id, user_id).first - case type - when "HomeworkCommon" - unless course_contributor_score.nil? - score = course_contributor_score.homework_journal_num.to_i - 1 - course_contributor_score.update_column(:homework_journal_num, score < 0 ? 0 : score) - end - # 课程留言 - when "Course" - unless course_contributor_score.nil? - score = course_contributor_score.journal_num.to_i - 1 - course_contributor_score.update_column(:journal_num, score < 0 ? 0 : score) - end - when "Message" - unless course_contributor_score.nil? - score = course_contributor_score.message_num.to_i - 1 - course_contributor_score.update_column(:message_num, score < 0 ? 0 : score) - end - when "MessageReply" - unless course_contributor_score.nil? - score = course_contributor_score.message_reply_num.to_i - 1 - course_contributor_score.update_column(:message_reply_num, score < 0 ? 0 : score) - end - when "NewReply" - unless course_contributor_score.nil? - score = course_contributor_score.news_reply_num.to_i - 1 - course_contributor_score.update_column(:news_reply_num, score < 0 ? 0 : score) - end - when "News" - unless course_contributor_score.nil? - score = course_contributor_score.news_num.to_i - 1 - course_contributor_score.update_column(:news_num, score < 0 ? 0 : score) - end - when "Attachment" - unless course_contributor_score.nil? - score = course_contributor_score.resource_num.to_i - 1 - course_contributor_score.update_column(:resource_num, score < 0 ? 0 : score) - end - end - end - - # Added by young - # Define the course menu's link class - # 不是数组的转化成数组,然后判断当前menu_item是否在给定的列表 - # REVIEW: 目测menu的机制,貌似不是很需要转换,再说 - def link_class(label) - labels = label.is_a?(Array) ? label : ([] << label) - #a = current_menu_item - labels.include?(current_menu_item) ? 'selected' : '' - - end - #Ended by young - # Return true if user is authorized for controller/action, otherwise false - def authorize_for(controller, action) - User.current.allowed_to?({:controller => controller, :action => action}, @project) - end - - # add by nwb - def authorize_for_course(controller, action) - User.current.allowed_to?({:controller => controller, :action => action}, @course) - end - - def authorize_for_contest(controller, action) - User.current.allowed_to?({:controller => controller, :action => action}, @contest) - end - - # Display a link if user is authorized - # - # @param [String] name Anchor text (passed to link_to) - # @param [Hash] options Hash params. This will checked by authorize_for to see if the user is authorized - # @param [optional, Hash] html_options Options passed to link_to - # @param [optional, Hash] parameters_for_method_reference Extra parameters for link_to - def link_to_if_authorized(name, options = {}, html_options = nil, *parameters_for_method_reference) - link_to(name, options, html_options, *parameters_for_method_reference) if authorize_for(options[:controller] || params[:controller], options[:action]) - end - - def link_to_if_authorized_course(name, options = {}, html_options = nil, *parameters_for_method_reference) - link_to(name, options, html_options, *parameters_for_method_reference) if authorize_for_course(options[:controller] || params[:controller], options[:action]) - end - - def link_to_if_authorized_contest(name, options = {}, html_options = nil, *parameters_for_method_reference) - link_to(name, options, html_options, *parameters_for_method_reference) if authorize_for_contest(options[:controller] || params[:controller], options[:action]) - end - # Displays a link to user's account page if active - def link_to_user(user, canShowRealName = false, options={}) - if user.is_a?(User) - if canShowRealName - name = h(user.realname(options[:format])) - else - name = h(user.name(options[:format])) - end - - #if user.active? || (User.current.admin? && user.logged?) - # link_to name, {:controller=> 'users', :action => 'show', id: user.id, host: Setting.host_user}, :class => user.css_classes - #else - # name - #end - link_to name, {:controller=> 'users', :action => 'show', id: user.id, host: Setting.host_user}, :class => user.css_classes - else - h(user.to_s) - end - end - - def link_to_isuue_user(user, options={}) - if user.is_a?(User) - if options[:format] - name = h(user.name(options[:format])) - else - name = h(user.show_name) - end - link_to name, {:controller=> 'users', :action => 'show', id: user.id, host: Setting.host_user}, :class => "pro_info_p" - else - h(user.to_s) - end - end - - def link_to_settings_user(user, options={}) - if user.is_a?(User) - name = h(user.name(options[:format])) - link_to name, {:controller=> 'users', :action => 'show', id: user.id, host: Setting.host_user}, :class => "w90 c_orange fl" - else - h(user.to_s) - end - end - - #重载上面方法,增加样式显示 - def link_to_user_header user,canShowRealName=false,options={} - if user.is_a?(User) - if canShowRealName - name = user.show_name - name = user.login if name == "" - else - name = user.login - end - link_to name, {:controller=> 'users', :action => 'show', id: user.id, host: Setting.host_user}, :class => options[:class] - else - h(user.to_s) - end - end - - # Displays a link to +issue+ with its subject. - # Examples: - # - # link_to_issue(issue) # => Defect #6: This is the subject - # link_to_issue(issue, :truncate => 6) # => Defect #6: This i... - # link_to_issue(issue, :subject => false) # => Defect #6 - # link_to_issue(issue, :project => true) # => Foo - Defect #6 - # link_to_issue(issue, :subject => false, :tracker => false) # => #6 - # - def link_to_issue(issue, options={}) - title = nil - subject = nil - text = options[:tracker] == false ? "##{issue.id}" : "#{issue.tracker} ##{issue.id}" - if options[:subject] == false - title = truncate(issue.subject, :length => 60) - else - subject = issue.subject - if options[:truncate] - subject = truncate(subject, :length => options[:truncate]) - end - end - s = link_to text, issue_path(issue), :class => issue.css_classes, :title => title - s << h(": #{subject}") if subject - s = h("#{issue.project} - ") + s if options[:project] - s - end - - def link_to_issue_version(issue, options={}) - title = nil - subject = nil - text = options[:tracker] == false ? "##{issue.id}" : "#{issue.tracker} ##{issue.id}" - if options[:subject] == false - title = truncate(issue.subject, :length => 60) - else - subject = issue.subject - if options[:truncate] - subject = truncate(subject, :length => 60) - end - end - # status_id:3、已解决 5、已关闭 - if issue.status_id == 3 - s = link_to text, issue_path(issue), :class => "text_line_s fl", :title => title - elsif issue.status_id == 5 - s = link_to text, issue_path(issue), :class => "text_line_s del_line fl", :title => title - else - s = link_to text, issue_path(issue), :class => "c_blue fl", :title => title - end - s << h("".html_safe) if subject - s = h("#{issue.project} - ") + s if options[:project] - s - end - - # Generates a link to an attachment. - # Options: - # * :text - Link text (default to attachment filename) - # * :download - Force download (default: false) - def link_to_short_attachment(attachment, options={}) - length = options[:length] ? options[:length]:23 - text = h(truncate(options.delete(:text) || attachment.filename, length: length, omission: '...')) - route_method = options.delete(:download) ? :download_named_attachment_url_without_domain : :named_attachment_url_without_domain - html_options = options.slice!(:only_path) - url = send(route_method, attachment, attachment.filename, options) - link_to text, url, html_options - end - - # Generates a link to an attachment. - # Options: - # * :text - Link text (default to attachment filename) - # * :download - Force download (default: false) - def link_to_attachment(attachment, options={}) - token = options[:token] if options[:token] - text = options.delete(:text) || attachment.filename - route_method = options.delete(:download) ? :download_named_attachment_path : :named_attachment_path - html_options = options.slice!(:only_path) - url = send(route_method, attachment, attachment.filename, options) - url << "?token=#{token}" unless token.nil? - link_to text, url, html_options - end - - def link_to_attachment_img(attachment, options={}) - text = options.delete(:text) || attachment.filename - route_method = options.delete(:download) ? :download_named_attachment_path : :named_attachment_path - html_options = options.slice!(:only_path) - url = send(route_method, attachment, attachment.filename, options) - image_tag url, html_options - end - - # Generates a link to a SCM revision - # Options: - # * :text - Link text (default to the formatted revision) - def link_to_revision(revision, repository, options={}) - if repository.is_a?(Project) - repository = repository.repository - end - text = options.delete(:text) || format_revision(revision) - rev = revision.respond_to?(:identifier) ? revision.identifier : revision - link_to( - h(text), - {:controller => 'repositories', :action => 'revision', :id => repository.project, :repository_id => repository.identifier_param, :rev => rev}, - :title => l(:label_revision_id, format_revision(revision)) - ) - end - - # Generates a link to a message - def link_to_message(message, options={}, html_options = nil) - link_to( - truncate(message.subject, :length => 60), - board_message_path(message.board_id, message.parent_id || message.id, { - :r => (message.parent_id && message.id), - :anchor => (message.parent_id ? "message-#{message.id}" : nil) - }.merge(options)), - html_options - ) - end - - # Generates a link to a project if active - # Examples: - # - # link_to_project(project) # => link to the specified project overview - # link_to_project(project, {:only_path => false}, :class => "project") # => 3rd arg adds html options - # link_to_project(project, {}, :class => "project") # => html options with default url (project overview) - # - def link_to_project(project, options={}, html_options = nil) - if project.archived? - h(project.name) - elsif options.key?(:action) - ActiveSupport::Deprecation.warn "#link_to_project with :action option is deprecated and will be removed in Redmine 3.0." - url = {:controller => 'projects', :action => 'show', :id => project}.merge(options) - link_to project.name, url, html_options - else - link_to project.name, project_path(project, options), html_options - end - end - - def link_to_course(course, options={}, html_options = nil) - if course.archived? - h(course.name) - elsif options.key?(:action) - ActiveSupport::Deprecation.warn "#link_to_course with :action option is deprecated and will be removed in Redmine 3.0." - url = {:controller => 'courses', :action => 'show', :id => project}.merge(options) - link_to course.name, url, html_options - else - link_to course.name, course_path(course, options), html_options - end - end - - # Generates a link to a project settings if active - def link_to_project_settings(project, options={}, html_options=nil) - if project.active? - link_to project.name, settings_project_path(project, options), html_options - elsif project.archived? - h(project.name) - else - link_to project.name, project_path(project, options), html_options - end - end - - def wiki_page_path(page, options={}) - url_for({:controller => 'wiki', :action => 'show', :project_id => page.project, :id => page.title}.merge(options)) - end - - def thumbnail_tag(attachment) - link_to image_tag(thumbnail_path(attachment)), - named_attachment_path(attachment, attachment.filename), - :title => attachment.filename - end - - def thumbnail_issue_tag(attachment) - imagesize = attachment.thumbnail(:size => "200*200") - imagepath = named_attachment_path(attachment, attachment.filename) - if imagesize - link_to image_tag(thumbnail_path(attachment), height: '73', width: '100', class: 'issue_attachment_picture'), - imagepath, - :title => attachment.filename - - else - link_to image_tag(imagepath , height: '73', width: '100', class: 'issue_attachment_picture'), - imagepath, - :title => attachment.filename - end - end - - def thumbnail_challenge_tag(attachment) - imagepath = named_attachment_path(attachment, attachment.filename) - image_tag(imagepath) - end - - # 图片缩略图链接 - def thumbnail_small_tag(attachment) - imagesize = attachment.thumbnail(:size => "200*200") - imagepath = named_attachment_path(attachment, attachment.filename) - if imagesize - link_to image_tag(imagesize), - imagepath, - :title => attachment.filename - else - link_to image_tag(imagepath , height: '200', width: '250'), - imagepath, - :title => attachment.filename - end - end - - def toggle_link(name, id, options={}) - onclick = "$('##{id}').slideToggle(); " - onclick << (options[:focus] ? "$('##{options[:focus]}').focus(); " : "this.blur(); ") - onclick << "return false;" - link_to(name, "javascript:void(0)", :onclick => onclick,:class => options[:class]) - end - - def image_to_function(name, function, html_options = {}) - html_options.symbolize_keys! - tag(:input, html_options.merge({ - :type => "image", :src => image_path(name), - :onclick => (html_options[:onclick] ? "#{html_options[:onclick]}; " : "") + "#{function};" - })) - end - - def format_activity_title(text) - h(truncate_single_line(text, :length => 100)) - end - - def format_activity_day(date) - date == User.current.today ? l(:label_today).titleize : format_date(date) - end - - def format_activity_description(text) - h(truncate(text.to_s, :length => 120).gsub(%r{[\r\n]*<(pre|code)>.*$}m, '...')).gsub(/[\r\n]+/, "
").html_safe - #h(truncate(text.to_s, :length => 120).gsub(/<\/?.*?>/,"")).html_safe - end - - def format_version_name(version) - if version.project == @project - h(truncate(version.name,:length=>20)) - else - h("#{version.project} - #{truncate(version.name,:length=>20)}") - end - end - - def due_date_distance_in_words(date) - if date - l((date < Date.today ? :label_roadmap_overdue : :label_roadmap_due_in), distance_of_date_in_words(Date.today, date)) - end - end - - # Renders a tree of projects as a nested set of unordered lists - # The given collection may be a subset of the whole project tree - # (eg. some intermediate nodes are private and can not be seen) - #Modified by nie. - def render_project_nested_lists(projects) - s = '' - if projects.any? - ancestors = [] - original_project = @project - #modified by nie - projects.each do |project| - # set the project environment to please macros. - @project = project - if (ancestors.empty? || project.is_descendant_of?(ancestors.last)) -# s << "\n" * ancestors.size) - @project = original_project - end - s.html_safe - end - - def render_course_nested_lists(courses) - s = '' - if courses.any? - ancestors = [] - original_course = @course - #modified by nie - courses.each do |course| - # set the project environment to please macros. - @course = course - if (ancestors.empty? )#|| course.is_descendant_of?(ancestors.last)) - s << "\n" - end - end - classes = (ancestors.empty? ? 'root' : 'child') - s << "
  • " - - s << (render :partial => 'courses/course', :locals => {:course => course}).to_s - s << "
    \n" - ancestors << course - end - s << ("
  • \n" * ancestors.size) - @course = original_course - end - s.html_safe - end - - - #added by young - def render_project_nested_lists_new(projects) - s = '' - if projects.any? - ancestors = [] - original_project = @project - projects.sort_by(&:lft).each do |project| - # set the project environment to please macros. - @project = project - if (ancestors.empty? || project.is_descendant_of?(ancestors.last)) -# s << "\n" * ancestors.size) - @project = original_project - end - s.html_safe - end - #end - def render_page_hierarchy(pages, node=nil, options={}) - content = '' - if pages[node] - content << "\n" - end - content.html_safe - end - - # Renders flash messages - def render_flash_messages - s = '' - flash.each do |k,v| - s << content_tag('div', v.html_safe, :class => "alert alert-orange mb15 mt15", :id => "flash_#{k}") - end - s.html_safe - end - - # Renders tabs and their content - def render_tabs(tabs) - if tabs.any? - render :partial => 'common/tabs', :locals => {:tabs => tabs} - else - content_tag 'p', l(:label_no_data), :class => "nodata" - end - end - - def render_project_settings_tabs(tabs) - if tabs.any? - render :partial => 'common/project_tab', :locals => {:tabs => tabs} - else - content_tag 'p', l(:label_no_data), :class => "nodata" - end - end - - # Renders the project quick-jump box - def render_project_jump_box - return unless User.current.logged? - projects = User.current.memberships.collect(&:project).compact.select(&:active?).uniq - if projects.any? - options = - ("" + - '').html_safe - - options << project_tree_options_for_select(projects, :selected => @project) do |p| - { :value => project_path(:id => p, :jump => current_menu_item) } - end - - select_tag('project_quick_jump_box', options, :onchange => 'if (this.value != \'\') { window.location = this.value; }') - end - end - - def project_tree_options_for_select(projects, options = {}) - s = '' - project_tree(projects) do |project, level| - name_prefix = (level > 0 ? ' ' * 2 * level + '» ' : '').html_safe - tag_options = {:value => project.id} - tag_options[:title] = project.name - if project == options[:selected] || (options[:selected].respond_to?(:include?) && options[:selected].include?(project)) - tag_options[:selected] = 'selected' - else - tag_options[:selected] = nil - end - tag_options.merge!(yield(project)) if block_given? - s << content_tag('option', name_prefix + h(project), tag_options) - end - s.html_safe - end - - # Yields the given block for each project with its level in the tree - # - # Wrapper for Project#project_tree - def project_tree(projects, &block) - Project.project_tree(projects, &block) - end - - # 项目版本库可见权限判断: - # modules中设置可见 - # 版本库存在 - # 版本库设置了隐藏则仅仅项目成员或超级管理员可见(hidden_repo:1 隐藏版本库) - # return -> true 可见 - def visible_repository?(project) - repository = Repository.where(:project_id => project.id, :type => "Repository::Gitlab").first - if project.enabled_modules.where("name = 'repository'").empty? || repository.nil? - result = false - else - result = (project.hidden_repo && !User.current.admin && !User.current.member_of?(project)) ? false : true - end - end - - # 判断成员在项目中的角色 member_role == Reporter/Manager/Developer 报告人员/管理人员/报告人员; - def role_of_members_in_project(project, user_id) - member = Member.where(:project_id => project, :user_id => user_id) - unless member.blank? - member_role = member.first.roles[0].to_s - end - return member_role - end - - # 判断用户是不是项目成员 - def is_project_member?(user_id, project_id) - @result = false - mem = Member.where("user_id = ? and project_id = ?",user_id, project_id) - unless mem.blank? - @result = true - end - return @result - end - - # 更新各类消息为已读 - def update_messsages_to_viewed(message_type, forge_message_id) - if(message_type == "CourseMessage") - query = CourseMessage.where(:course_message_type => ["JoinCourse", "RemoveFromCourse"], - :user_id => User.current, - :course_id => forge_message_id, - :viewed => false) - elsif(message_type == "ForgeMessage") - query = ForgeMessage.where(:forge_message_type => ["ProjectInvite", "JoinProject", "RemoveFromProject"], - :user_id => User.current, - :project_id => forge_message_id, - :viewed => false) - elsif(message_type == "ContestMessage") - query = ContestMessage.where(:contest_message_type => ["ContestRequestDealResult", "JoinContest", "RemoveFromContest"], - :user_id => User.current, - :contest_id => forge_message_id, - :viewed => false) - elsif(message_type == "BlogMessage") - query = BlogMessage.where(:blog_message_type => "BlogComment", - :user_id => User.current, - :blog_id => forge_message_id, - :viewed => false) - end - query.update_all(:viewed => true) unless query.blank? - end - - def show_attachment_tip container_id, container_type - atts = Attachment.where(:container_id => container_id, :container_type => container_type, :is_public => 0) - atts.count > 0 ? true :false - end - - # 必须是项目成员,项目必须提交过代码 - def allow_pull_request project - return 0 if project.gpid.nil? - g = Gitlab.client - # 之所以这样比较是为了解决gitlab本身的bug - commit_count = g.project(project.gpid).try(:commit_count).to_i - git_commit_cout = g.user_static(project.gpid, :rev => "master").count - count = commit_count > git_commit_cout ? commit_count : git_commit_cout - count - end - - # 判断版本库是否初始为gitlab - def rep_is_gitlab?(project) - rep = project.repositories.where("type =?", "Repository::Gitlab") - return rep.blank? ? true :false - end - - # 获取Gitlab版本库提交总数 - def commit_count(project, branch) - g = Gitlab.client - #add by hx - if g.commits(project.gpid, :ref_name => @rev , :page=>200).count > 0 - count = 4020 - elsif g.commits(project.gpid , :page=>25, :ref_name => branch).count==0 - count = count_commits(project.gpid , 0 , 25) - elsif g.commits(project.gpid , :page=>50, :ref_name => branch).count ==0 - count = count_commits(project.gpid , 25 , 50)+ 25 * 20 - elsif g.commits(project.gpid , :page=>75, :ref_name => branch).count ==0 - count = count_commits(project.gpid , 50 , 75)+ 50 * 20 - elsif g.commits(project.gpid , :page=>100, :ref_name => branch).count== 0 - count = count_commits(project.gpid , 75 , 100) + 75 * 20 - elsif g.commits(project.gpid , :page=>125, :ref_name => branch).count==0 - count = count_commits(project.gpid , 100 , 125) + 100 * 20 - elsif g.commits(project.gpid , :page=>150, :ref_name => branch).count==0 - count = count_commits(project.gpid , 125 , 150) + 125 * 20 - else - count = count_commits(project.gpid , 150 ,200) + 150 * 20 - end - end - - #add by hx - def count_commits(project_id , left , right) - count = 0 - (left..right).each do |page| - if $g.commits(project_id,:page => page).count == 0 - break - else - count = count + $g.commits(project_id, :ref_name => @rev, :page => page).count - end - end - return count - end - - # 获取单一gitlab项目 - def gitlab_repository(project) - rep = Repository.where("project_id =? and type =?", project.id,"Repository::Gitlab" ).first - end - - # 获取单一gitlab项目 - def shixun_repository(shixun) - rep = Repository.where(:shixun_id => shixun, :type => "Repository::Gitlab" ).first - end - - # 判断当前用户是否为项目管理员 - def is_project_manager?(user_id, project_id) - @result = false - mem = Member.where("user_id = ? and project_id = ?",user_id, project_id) - unless mem.blank? - @result = mem.first.roles.to_s.include?("Manager") ? true : false - end - return @result - end - - # 公开项目资源可以引用,admin和管理员和资源上传者拥有设置公开私有权限 - def authority_pubilic_for_files(project, file) - @result = false - if (is_project_manager?(User.current.id, @project.id) && User.current.allowed_to?(:manage_files, project)) || file.author_id == User.current.id || User.current.admin && - project_contains_attachment?(project,file) && file.container_id == project.id && file.container_type == "Project" - @result = true - end - return @result - end - - def principals_check_box_tags(name, principals) - s = '' - principals.each do |principal| - s << "\n" - end - s.html_safe - end - - # 判断模块是否可见 - def project_modules_allow project - @project.enabled_modules.where("name = 'issue_tracking'").empty? - end - - # 计算Pull Request的请求数目 - def pull_request_count project - g = Gitlab.client - g.merge_requests(project.gpid).count - end - - #项目成员列表复选框生成 - def project_member_check_box_tags_ex name, principals - s = '' - principals.each do |principal| - s << "
  • #{ check_box_tag name, principal.id, false, :id => nil} #{h link_to principal.userInfo, user_url_in_org( principal), :target => "_blank"}
  • \n" - end - s.html_safe - end - - def render_shixun_departments - s = '' - if params[:q] && params[:q].lstrip.rstrip != "" - scope = School.where("name like ?", "%#{params[:q]}%") - else - scope = [] - end - scope.each do |name| - s << "
  • #{name}
  • \n" - end - s.html_safe - end - - # REDO:发现搜索列表的功能还是挺多,以前单独写的最好都调用这个方法 - # scope:[] - def render_mirror_name scope = nil - s = '' - if scope.present? - scope.each do |name| - s << "
  • #{name}
  • \n" - end - end - s.html_safe - end - - #缺陷追踪者列表复选框生成 - def issue_watcher_check_box_tags_ex name, principals - s = '' - principals.each do |principal| - s << "
  • #{ check_box_tag name, principal.id, false, :id => nil } #{h link_to principal.userInfo, user_path( principal.id)}
  • \n" - end - s.html_safe - end - - - - #扩展的checkbox生成 - def principals_check_box_tags_ex(name, principals) - s = '' - principals.each do |principal| - s << "\n" - end - s.html_safe - end - - # li标签checkbos扩展 - def principals_check_box_tags_li(name, principals) - s = '' - principals.each do |principal| - s << "
  • #{ check_box_tag name, principal.id, false, :id => nil } #{h link_to principal.userInfo, user_path( principal.id) }
  • \n" - end - s.html_safe - end - - #扩展的checkbox生成 - def principals_radio_box_tags_ex(name, principals) - s = '' - principals.each do |principal| - s << "\n" - end - s.html_safe - end - - - # Returns a string for users/groups option tags - def principals_options_for_select(collection, selected=nil) - s = '' - if collection.include?(User.current) - s << content_tag('option', "<< #{l(:label_me)} >>", :value => User.current.id) - end - groups = '' - collection.sort.each do |element| - selected_attribute = ' selected="selected"' if option_value_selected?(element, selected) - (element.is_a?(Group) ? groups : s) << %() - end - unless groups.empty? - s << %(#{groups}) - end - s.html_safe - end - - def assigned_options_for_select(collection, selected=nil) - conv = Iconv.new("GBK", "utf-8") - s = '' - s << content_tag('option', "#{l(:label_assiged_tip)}", :value => 0) - if collection.include?(User.current) - s << content_tag('option', "<< #{l(:label_me)} >>", :value => User.current.id) - end - groups = '' - collection.sort{|x, y| conv.iconv(x.lastname) <=> conv.iconv(y.lastname)}.each do |element| - selected_attribute = ' selected="selected"' if option_value_selected?(element, selected) - (element.is_a?(Group) ? groups : s) << %() - end - unless groups.empty? - s << %(#{groups}) - end - s.html_safe - end - - - # Options for the new membership projects combo-box - def options_for_membership_project_select(principal, projects) - options = content_tag('option', "--- #{l(:actionview_instancetag_blank_option)} ---") - options << project_tree_options_for_select(projects) do |p| - {:disabled => principal.projects.to_a.include?(p)} - end - options - end - - # Truncates and returns the string as a single line - def truncate_single_line(string, *args) - truncate(string.to_s, *args).gsub(%r{[\r\n]+}m, ' ') - end - - # Truncates at line break after 250 characters or options[:length] - def truncate_lines(string, options={}) - length = options[:length] || 250 - if string.to_s =~ /\A(.{#{length}}.*?)$/m - "#{$1}..." - else - string - end - end - - def anchor(text) - text.to_s.gsub(' ', '_') - end - - def html_hours(text) - text.gsub(%r{(\d+)\.(\d+)}, '\1.\2').html_safe - end - - def authoring(created, author, options={}) - l(options[:label] || :label_added_time_by, :author => link_to_user(author), :age => time_tag(created)).html_safe - end - - def added_time(created) - l(:label_added_time, :age => time_tag(created)).html_safe - end - - def user_url_and_time(user_name, user_url, created) - unless user_name.nil? || user_name == '' - l(:label_added_time_by, :author => link_to(user_name, user_url), :age => time_tag(created)).html_safe - else - l(:label_added_time, :age => time_tag(created)).html_safe - end - end - - #huang - def betweentime(enddate) - ss=(DateTime.parse("#{enddate.to_date}")-DateTime.parse("#{DateTime.now.to_date}")).to_i - return ss - end - - def time_tag(time, *args) - options = args.extract_options! - text = distance_of_time_in_words(Time.now, time) - if @project - content_tag('acronym', text, options.reverse_merge(:title => format_time(time))) - # link_to(text, {:controller => 'activities', :action => 'index', :id => @project, :from => User.current.time_to_date(time)},options.reverse_merge(:title => format_time(time))) - else - content_tag('acronym', text, options.reverse_merge(:title => format_time(time))) - end - end - - def syntax_highlight_lines(name, content) - lines = [] - syntax_highlight(name, content).each_line { |line| lines << line } - lines - end - - def syntax_highlight(name, content) - Redmine::SyntaxHighlighting.highlight_by_filename(content, name) - end - - def to_path_param(path) - str = path.to_s.split(%r{[/\\]}).select{|p| !p.blank?}.join("/") - str.blank? ? nil : str - end - - def reorder_links(name, url, method = :post) - link_to(image_tag('2uparrow.png', :alt => l(:label_sort_highest)), - url.merge({"#{name}[move_to]" => 'highest'}), - :method => method, :title => l(:label_sort_highest)) + - link_to(image_tag('1uparrow.png', :alt => l(:label_sort_higher)), - url.merge({"#{name}[move_to]" => 'higher'}), - :method => method, :title => l(:label_sort_higher)) + - link_to(image_tag('1downarrow.png', :alt => l(:label_sort_lower)), - url.merge({"#{name}[move_to]" => 'lower'}), - :method => method, :title => l(:label_sort_lower)) + - link_to(image_tag('2downarrow.png', :alt => l(:label_sort_lowest)), - url.merge({"#{name}[move_to]" => 'lowest'}), - :method => method, :title => l(:label_sort_lowest)) - end - - def breadcrumb(*args) - elements = args.flatten - elements.any? ? content_tag('p', (args.join(" \xc2\xbb ") + " \xc2\xbb ").html_safe, :class => 'wiki_con_tit"') : nil - end - - def other_formats_links(&block) - concat('

    '.html_safe + l(:label_export_to)) - yield Redmine::Views::OtherFormatsBuilder.new(self) - concat('

    '.html_safe) - end - - def page_header_title - if @project.nil? || @project.new_record? - h(Setting.app_title) - else - b = [] - ancestors = (@project.root? ? [] : @project.ancestors.visible.all) - if ancestors.any? - root = ancestors.shift - b << link_to_project(root, {:jump => current_menu_item}, :class => 'root') - if ancestors.size > 2 - b << "\xe2\x80\xa6" - ancestors = ancestors[-2, 2] - end - b += ancestors.collect {|p| link_to_project(p, {:jump => current_menu_item}, :class => 'ancestor') } - end - b << h(@project) - b.join(" \xc2\xbb ").html_safe - end - end - - def html_title(*args) - #點擊項目版本庫 多觸發一次 字符串為"/" - #暫時解決方法 直接判斷 - if(args == ["/"]) - args = [] - end - # first_page = FirstPage.find_by_page_type('project') - if args.empty? - title = @html_title || [] - if @project - title << (@project.name.present? ? @project.name : "项目") - elsif params[:controller] == "projects" - title << "项目" - elsif @welcome - title << "创新源于实践" - elsif @course - title << (@course.name.nil? ? "课堂" : @course.name) - elsif params[:controller] == "homework_bank" || params[:controller] == "question_banks" || params[:controller] == "exercise_bank" - title << ("题库") - elsif params[:controller] == "managements" - title << ("后台管理") - elsif params[:controller] == "colleges" && params[:action] == "statistics" - title << ("#{@school.name}") - elsif params[:controller] == "account" && params[:action] == "help" - if params[:index] - case params[:index] - when "1" - title << ("关于我们") - when "2" - title << ("联系我们") - when "3" - title << ("合作伙伴") - when "4" - title << ("服务协议") - when "5" - title << ("帮助中心") - when "6" - title << ("意见反馈") - end - else - title << ("关于我们") - end - elsif params[:controller] == "courses" && params[:action] == "index" - title << ("翻转课堂") - elsif params[:controller] == "competitions" && params[:action] == "index" - title << ("竞赛") - elsif @competition - title << (@competition.name.nil? ? "竞赛" : @competition.name) - elsif @contest - title << (@contest.name.nil? ? "创新源于实践" : @contest.name) - elsif @shixun - title << (@shixun.name.nil? ? "开发社区" : @shixun.name) - elsif @my_shixun - title << ("我的实训") - elsif params[:controller] == "shixuns" && params[:action] == "index" - title << ("开发社区") - elsif @subject - title << (@subject.name.nil? ? "实训课程" : @subject.name) - elsif params[:controller] == "subjects" && params[:action] == "index" - title << ("实训课程") - elsif @organization - title << (@organization.name.nil? ? "创新源于实践" : @organization.name) - elsif @forum || params[:controller] == "forums" - title << "讨论区" - elsif @my_syllabuses - title << "我的课堂" - elsif params[:controller] == 'ecs' - title << '专业列表' - elsif params[:controller] == 'ec_major_schools' - name = EcMajorSchool.find(params[:id]).name - title << name - elsif params[:controller] == 'ec_years' - if params[:action] == 'training_objectives' - title << '培养目标' - elsif params[:action] == 'graduation_requirement' - title << '毕业要求' - elsif params[:action] == 'requirement_vs_objective' - title << '毕业要求 vs 培养目标' - elsif params[:action] == 'requirement_vs_standard' - title << '毕业要求 vs 通用标准' - elsif params[:action] == 'ec_course_setting' || params[:action] == 'completion_calculation' - title << '课程体系' - else - title << '工程认证' - end - elsif params[:controller] == 'ec_courses' - if params[:action] == 'ec_course_support_setting' - title << '课程体系 vs 毕业要求' - end - elsif @user - if !@project_community.blank? || !@user_projectlist.blank? - title << "项目" - elsif !@course_community.blank? || !@user_courselist.blank? - title << "课堂" - elsif !@contest_community.blank? - title << @contest_community - elsif !@manage_issues.blank? - title << @manage_issues - elsif !@receive_issues.blank? - title << @receive_issues - elsif !@manage_homeworks.blank? - title << @manage_homeworks - elsif !@receive_homeworks.blank? - title << @receive_homeworks - else - title << @user.show_name - end - elsif @syllabus - title << (@syllabus.title.nil? ? "课堂" : @syllabus.title) - else - title << (User.current.id == 2 ? "未登录" : User.current.show_name) - end - # if first_page.nil? || first_page.web_title.nil? - # title << Setting.app_title unless Setting.app_title == title.last - # else - # title << first_page.web_title unless first_page.web_title == title.last - # end - title.select {|t| !t.blank? }.join(' - ') - else - @html_title ||= [] - @html_title += args - end - end - - # Returns the theme, controller name, and action as css classes for the - # HTML body. - def body_css_classes - css = [] - if theme = Redmine::Themes.theme(Setting.ui_theme) - css << 'theme-' + theme.name - end - - css << 'controller-' + controller_name - css << 'action-' + action_name - css.join(' ') - end - - def accesskey(s) - @used_accesskeys ||= [] - key = Redmine::AccessKeys.key_for(s) - return nil if @used_accesskeys.include?(key) - @used_accesskeys << key - key - end - - # Formats text according to system settings. - # 2 ways to call this method: - # * with a String: textilizable(text, options) - # * with an object and one of its attribute: textilizable(issue, :description, options) - def textilizable(*args) - options = args.last.is_a?(Hash) ? args.pop : {} - case args.size - when 1 - obj = options[:object] - text = args.shift - when 2 - obj = args.shift - attr = args.shift - text = obj.send(attr).to_s - else - raise ArgumentError, 'invalid arguments to textilizable' - end - return '' if text.blank? - project = options[:project] || @project || (obj && obj.respond_to?(:project) ? obj.project : nil) - only_path = options.delete(:only_path) == false ? false : true - - text = text.dup - macros = catch_macros(text) - text = Redmine::WikiFormatting.to_html(Setting.text_formatting, text, :object => obj, :attribute => attr) - - @parsed_headings = [] - @heading_anchors = {} - @current_section = 0 if options[:edit_section_links] - - parse_sections(text, project, obj, attr, only_path, options) - text = parse_non_pre_blocks(text, obj, macros) do |text| - [:parse_inline_attachments, :parse_wiki_links, :parse_redmine_links].each do |method_name| - send method_name, text, project, obj, attr, only_path, options - end - end - parse_headings(text, project, obj, attr, only_path, options) - - if @parsed_headings.any? - replace_toc(text, @parsed_headings) - end - - text.html_safe - end - - # - #格式化字符串,不转义html代码 - def textAreailizable(*args) - options = args.last.is_a?(Hash) ? args.pop : {} - case args.size - when 1 - obj = options[:object] - text = args.shift - when 2 - obj = args.shift - attr = args.shift - text = obj.send(attr).to_s - else - raise ArgumentError, 'invalid arguments to textilizable' - end - return '' if text.blank? - project = options[:project] || @project || (obj && obj.respond_to?(:project) ? obj.project : nil) - only_path = options.delete(:only_path) == false ? false : true - - text = text.dup - macros = catch_macros(text) - #text = Redmine::WikiFormatting.to_html("CKEditor", text, :object => obj, :attribute => attr) - - @parsed_headings = [] - @heading_anchors = {} - @current_section = 0 if options[:edit_section_links] - - parse_sections(text, project, obj, attr, only_path, options) - text = parse_non_pre_blocks(text, obj, macros) do |text| - [:parse_inline_attachments, :parse_wiki_links, :parse_redmine_links].each do |method_name| - send method_name, text, project, obj, attr, only_path, options - end - end - parse_headings(text, project, obj, attr, only_path, options) - - if @parsed_headings.any? - replace_toc(text, @parsed_headings) - end - - text.html_safe - end - - def parse_non_pre_blocks(text, obj, macros) - s = StringScanner.new(text) - tags = [] - parsed = '' - while !s.eos? - s.scan(/(.*?)(<(\/)?(pre|code)(.*?)>|\z)/im) - text, full_tag, closing, tag = s[1], s[2], s[3], s[4] - if tags.empty? - yield text - inject_macros(text, obj, macros) if macros.any? - else - inject_macros(text, obj, macros, false) if macros.any? - end - parsed << text - if tag - if closing - if tags.last == tag.downcase - tags.pop - end - else - tags << tag.downcase - end - parsed << full_tag - end - end - # Close any non closing tags - while tag = tags.pop - parsed << "" - end - parsed - end - - def parse_inline_attachments(text, project, obj, attr, only_path, options) - # when using an image link, try to use an attachment, if possible - attachments = options[:attachments] || [] - attachments += obj.attachments if obj.respond_to?(:attachments) - if attachments.present? - text.gsub!(/src="([^\/"]+\.(bmp|gif|jpg|jpe|jpeg|png))"(\s+alt="([^"]*)")?/i) do |m| - filename, ext, alt, alttext = $1.downcase, $2, $3, $4 - # search for the picture in attachments - if found = Attachment.latest_attach(attachments, filename) - image_url = download_named_attachment_path(found, found.filename, :only_path => only_path) - desc = found.description.to_s.gsub('"', '') - if !desc.blank? && alttext.blank? - alt = " title=\"#{desc}\" alt=\"#{desc}\"" - end - "src=\"#{image_url}\"#{alt}" - else - m - end - end - end - end - - # 判断课程、项目、组织是否有权限删除历史资源 - # 项目管理员或者附件的作者可以删除 - # (is_project_manager?(User.current.id, @project.id) || User.current.id == history.author_id) - def allow_to_delete_attachment history - attachment = history.attachment - case attachment.try(:container_type) - when "Project" - result = is_project_manager?(User.current.id, attachment.container_id) || User.current.id == history.author_id || User.current.admin? - when "Course" - result = User.current.allowed_to?(:as_teacher, attachment.container) || User.current.id == history.author_id || User.current.admin? - when "OrgSubfield" - result = User.current.id == history.author_id || User.current.admin_of_org?(attachment.container) || User.current.admin? - end - end - - # Wiki links - # - # Examples: - # [[mypage]] - # [[mypage|mytext]] - # wiki links can refer other project wikis, using project name or identifier: - # [[project:]] -> wiki starting page - # [[project:|mytext]] - # [[project:mypage]] - # [[project:mypage|mytext]] - def parse_wiki_links(text, project, obj, attr, only_path, options) - text.gsub!(/(!)?(\[\[([^\]\n\|]+)(\|([^\]\n\|]+))?\]\])/) do |m| - link_project = project - esc, all, page, title = $1, $2, $3, $5 - if esc.nil? - if page =~ /^([^\:]+)\:(.*)$/ - identifier, page = $1, $2 - link_project = Project.find_by_identifier(identifier) || Project.find_by_name(identifier) - title ||= identifier if page.blank? - end - - if link_project && link_project.wiki - # extract anchor - anchor = nil - if page =~ /^(.+?)\#(.+)$/ - page, anchor = $1, $2 - end - anchor = sanitize_anchor_name(anchor) if anchor.present? - # check if page exists - wiki_page = link_project.wiki.find_page(page) - url = if anchor.present? && wiki_page.present? && (obj.is_a?(WikiContent) || obj.is_a?(WikiContent::Version)) && obj.page == wiki_page - "##{anchor}" - else - case options[:wiki_links] - when :local; "#{page.present? ? Wiki.titleize(page) : ''}.html" + (anchor.present? ? "##{anchor}" : '') - when :anchor; "##{page.present? ? Wiki.titleize(page) : title}" + (anchor.present? ? "_#{anchor}" : '') # used for single-file wiki export - else - wiki_page_id = page.present? ? Wiki.titleize(page) : nil - parent = wiki_page.nil? && obj.is_a?(WikiContent) && obj.page && project == link_project ? obj.page.title : nil - url_for(:only_path => only_path, :controller => 'wiki', :action => 'show', :project_id => link_project, - :id => wiki_page_id, :version => nil, :anchor => anchor, :parent => parent) - end - end - link_to(title.present? ? title.html_safe : h(page), User.current.logged? ? url : signin_url_without_domain, :class => ('wiki-page' + (wiki_page ? '' : ' new'))) - else - # project or wiki doesn't exist - all - end - else - all - end - end - end - - def select_option_helper option - tmp = Hash.new - tmp={"" => ""} - if option.nil? - else - option.each do |project| - tmp[project.name] = project.id - end - end - tmp - end - # Redmine links - # - # Examples: - # Issues: - # #52 -> Link to issue #52 - # Changesets: - # r52 -> Link to revision 52 - # commit:a85130f -> Link to scmid starting with a85130f - # Documents: - # document#17 -> Link to document with id 17 - # document:Greetings -> Link to the document with title "Greetings" - # document:"Some document" -> Link to the document with title "Some document" - # Versions: - # version#3 -> Link to version with id 3 - # version:1.0.0 -> Link to version named "1.0.0" - # version:"1.0 beta 2" -> Link to version named "1.0 beta 2" - # Attachments: - # attachment:file.zip -> Link to the attachment of the current object named file.zip - # Source files: - # source:some/file -> Link to the file located at /some/file in the project's repository - # source:some/file@52 -> Link to the file's revision 52 - # source:some/file#L120 -> Link to line 120 of the file - # source:some/file@52#L120 -> Link to line 120 of the file's revision 52 - # export:some/file -> Force the download of the file - # Forum messages: - # message#1218 -> Link to message with id 1218 - # - # Links can refer other objects from other projects, using project identifier: - # identifier:r52 - # identifier:document:"Some document" - # identifier:version:1.0.0 - # identifier:source:some/file - def parse_redmine_links(text, default_project, obj, attr, only_path, options) - text.gsub!(%r{([\s\(,\-\[\>]|^)(!)?(([a-z0-9\-_]+):)?(attachment|document|version|forum|news|message|project|commit|source|export)?(((#)|((([a-z0-9\-_]+)\|)?(r)))((\d+)((#note)?-(\d+))?)|(:)([^"\s<>][^\s<>]*?|"[^"]+?"))(?=(?=[[:punct:]][^A-Za-z0-9_/])|,|\s|\]|<|$)}) do |m| - leading, esc, project_prefix, project_identifier, prefix, repo_prefix, repo_identifier, sep, identifier, comment_suffix, comment_id = $1, $2, $3, $4, $5, $10, $11, $8 || $12 || $18, $14 || $19, $15, $17 - link = nil - project = default_project - if project_identifier - project = Project.visible.find_by_identifier(project_identifier) - end - if esc.nil? - if prefix.nil? && sep == 'r' - if project - repository = nil - if repo_identifier - repository = project.repositories.detect {|repo| repo.identifier == repo_identifier} - else - repository = project.repository - end - # project.changesets.visible raises an SQL error because of a double join on repositories - if repository && (changeset = Changeset.visible.find_by_repository_id_and_revision(repository.id, identifier)) - link = link_to(h("#{project_prefix}#{repo_prefix}r#{identifier}"), {:only_path => only_path, :controller => 'repositories', :action => 'revision', :id => project, :repository_id => repository.identifier_param, :rev => changeset.revision}, - :class => 'changeset', - :title => truncate_single_line(changeset.comments, :length => 100)) - end - end - elsif sep == '#' - oid = identifier.to_i - case prefix - when nil - if oid.to_s == identifier && issue = Issue.visible.find_by_id(oid, :include => :status) - anchor = comment_id ? "note-#{comment_id}" : nil - link = link_to("##{oid}", {:only_path => only_path, :controller => 'issues', :action => 'show', :id => oid, :anchor => anchor}, - :class => issue.css_classes, - :title => "#{truncate(issue.subject, :length => 100)} (#{issue.status.name})") - end - when 'document' - if document = Document.visible.find_by_id(oid) - link = link_to h(document.title), {:only_path => only_path, :controller => 'documents', :action => 'show', :id => document}, - :class => 'document' - end - when 'version' - if version = Version.visible.find_by_id(oid) - link = link_to h(version.name), {:only_path => only_path, :controller => 'versions', :action => 'show', :id => version}, - :class => 'version' - end - when 'message' - if message = Message.visible.find_by_id(oid, :include => :parent) - link = link_to_message(message, {:only_path => only_path}, :class => 'message') - end - when 'forum' - if board = Board.visible.find_by_id(oid) - link = link_to h(board.name), {:only_path => only_path, :controller => 'boards', :action => 'show', :id => board, :project_id => board.project}, - :class => 'board' - end - when 'news' - if news = News.visible.find_by_id(oid) - link = link_to h(news.title), {:only_path => only_path, :controller => 'news', :action => 'show', :id => news}, - :class => 'news' - end - when 'project' - if p = Project.visible.find_by_id(oid) - link = link_to_project(p, {:only_path => only_path}, :class => 'project') - end - end - elsif sep == ':' - # removes the double quotes if any - name = identifier.gsub(%r{^"(.*)"$}, "\\1") - case prefix - when 'document' - if project && document = project.documents.visible.find_by_title(name) - link = link_to h(document.title), {:only_path => only_path, :controller => 'documents', :action => 'show', :id => document}, - :class => 'document' - end - when 'version' - if project && version = project.versions.visible.find_by_name(name) - link = link_to h(version.name), {:only_path => only_path, :controller => 'versions', :action => 'show', :id => version}, - :class => 'version' - end - when 'forum' - if project && board = project.boards.visible.find_by_name(name) - link = link_to h(board.name), {:only_path => only_path, :controller => 'boards', :action => 'show', :id => board, :project_id => board.project}, - :class => 'board' - end - when 'news' - if project && news = project.news.visible.find_by_title(name) - link = link_to h(news.title), {:only_path => only_path, :controller => 'news', :action => 'show', :id => news}, - :class => 'news' - end - when 'commit', 'source', 'export' - if project - repository = nil - if name =~ %r{^(([a-z0-9\-_]+)\|)(.+)$} - repo_prefix, repo_identifier, name = $1, $2, $3 - repository = project.repositories.detect {|repo| repo.identifier == repo_identifier} - else - repository = project.repository - end - if prefix == 'commit' - if repository && (changeset = Changeset.visible.where("repository_id = ? AND scmid LIKE ?", repository.id, "#{name}%").first) - link = link_to h("#{project_prefix}#{repo_prefix}#{name}"), {:only_path => only_path, :controller => 'repositories', :action => 'revision', :id => project, :repository_id => repository.identifier_param, :rev => changeset.identifier}, - :class => 'changeset', - :title => truncate_single_line(changeset.comments, :length => 100) - end - else - if repository && User.current.allowed_to?(:browse_repository, project) - name =~ %r{^[/\\]*(.*?)(@([^/\\@]+?))?(#(L\d+))?$} - path, rev, anchor = $1, $3, $5 - link = link_to h("#{project_prefix}#{prefix}:#{repo_prefix}#{name}"), {:controller => 'repositories', :action => (prefix == 'export' ? 'raw' : 'entry'), :id => project, :repository_id => repository.identifier_param, - :path => to_path_param(path), - :rev => rev, - :anchor => anchor}, - :class => (prefix == 'export' ? 'source download' : 'source') - end - end - repo_prefix = nil - end - when 'attachment' - attachments = options[:attachments] || (obj && obj.respond_to?(:attachments) ? obj.attachments : nil) - if attachments && attachment = Attachment.latest_attach(attachments, name) - link = link_to_attachment(attachment, :only_path => only_path, :download => true, :class => 'attachment') - end - when 'project' - if p = Project.visible.where("identifier = :s OR LOWER(name) = :s", :s => name.downcase).first - link = link_to_project(p, {:only_path => only_path}, :class => 'project') - end - end - end - end - (leading + (link || "#{project_prefix}#{prefix}#{repo_prefix}#{sep}#{identifier}#{comment_suffix}")) - end - end - - HEADING_RE = /(]+)?>(.+?)<\/h(\d)>)/i unless const_defined?(:HEADING_RE) - - def parse_sections(text, project, obj, attr, only_path, options) - return unless options[:edit_section_links] - text.gsub!(HEADING_RE) do - heading = $1 - @current_section += 1 - if @current_section > 1 - content_tag('div', - link_to(image_tag('edit.png'), options[:edit_section_links].merge(:section => @current_section)), - :class => 'contextual', - :title => l(:button_edit_section)) + heading.html_safe - else - heading - end - end - end - - # Headings and TOC - # Adds ids and links to headings unless options[:headings] is set to false - def parse_headings(text, project, obj, attr, only_path, options) - return if options[:headings] == false - - text.gsub!(HEADING_RE) do - level, attrs, content = $2.to_i, $3, $4 - item = strip_tags(content).strip - anchor = sanitize_anchor_name(item) - # used for single-file wiki export - anchor = "#{obj.page.title}_#{anchor}" if options[:wiki_links] == :anchor && (obj.is_a?(WikiContent) || obj.is_a?(WikiContent::Version)) - @heading_anchors[anchor] ||= 0 - idx = (@heading_anchors[anchor] += 1) - if idx > 1 - anchor = "#{anchor}-#{idx}" - end - @parsed_headings << [level, anchor, item] - "\n#{content}" - end - end - - MACROS_RE = /( - (!)? # escaping - ( - \{\{ # opening tag - ([\w]+) # macro name - (\(([^\n\r]*?)\))? # optional arguments - ([\n\r].*?[\n\r])? # optional block of text - \}\} # closing tag - ) - )/mx unless const_defined?(:MACROS_RE) - - MACRO_SUB_RE = /( - \{\{ - macro\((\d+)\) - \}\} - )/x unless const_defined?(:MACRO_SUB_RE) - - # Extracts macros from text - def catch_macros(text) - macros = {} - text.gsub!(MACROS_RE) do - all, macro = $1, $4.downcase - if macro_exists?(macro) || all =~ MACRO_SUB_RE - index = macros.size - macros[index] = all - "{{macro(#{index})}}" - else - all - end - end - macros - end - - # Executes and replaces macros in text - def inject_macros(text, obj, macros, execute=true) - text.gsub!(MACRO_SUB_RE) do - all, index = $1, $2.to_i - orig = macros.delete(index) - if execute && orig && orig =~ MACROS_RE - esc, all, macro, args, block = $2, $3, $4.downcase, $6.to_s, $7.try(:strip) - if esc.nil? - h(exec_macro(macro, obj, args, block) || all) - else - h(all) - end - elsif orig - h(orig) - else - h(all) - end - end - end - - TOC_RE = /

    \{\{([<>]?)toc\}\}<\/p>/i unless const_defined?(:TOC_RE) - - # Renders the TOC with given headings - def replace_toc(text, headings) - text.gsub!(TOC_RE) do - # Keep only the 4 first levels - headings = headings.select{|level, anchor, item| level <= 4} - if headings.empty? - '' - else - div_class = 'toc' - div_class << ' right' if $1 == '>' - div_class << ' left' if $1 == '<' - out = "

    ' * (current - root) - out << '' - end - end - end - - # Same as Rails' simple_format helper without using paragraphs - def simple_format_without_paragraph(text) - text.to_s. - gsub(/\r\n?/, "\n"). # \r\n and \r -> \n - gsub(/\n\n+/, "

    "). # 2+ newline -> 2 br - gsub(/([^\n]\n)(?=[^\n])/, '\1
    '). # 1 newline -> br - html_safe - end - - def wiki_simple_format_without_paragraph(text) - text.to_s. - gsub(/\r\n?/, "\n"). # \r\n and \r -> \n - gsub(/\n\n+/, "

    "). # 2+ newline -> 2 br - gsub(/([^\n]\n)(?=[^\n])/, '\1
    '). # 1 newline -> br - gsub("&nbsp", " "). #gsub(/<\/?.*?>/,""). - gsub(/<\/?.*?>/, ""). - gsub(""", "'"). - html_safe - end - - def lang_options_for_select(blank=true) - { 'Chinese简体中文 '=> 'zh', :English => :en} - end - - def label_tag_for(name, option_tags = nil, options = {}) - label_text = l(("field_"+field.to_s.gsub(/\_id$/, "")).to_sym) + (options.delete(:required) ? @template.content_tag("span", " *", :class => "required"): "") - content_tag("label", label_text) - end - - def labelled_form_for(*args, &proc) - args << {} unless args.last.is_a?(Hash) - options = args.last - if args.first.is_a?(Symbol) - options.merge!(:as => args.shift) - end - options.merge!({:builder => Redmine::Views::LabelledFormBuilder}) - form_for(*args, &proc) - end - - def labelled_fields_for(*args, &proc) - args << {} unless args.last.is_a?(Hash) - options = args.last - options.merge!({:builder => Redmine::Views::LabelledFormBuilder}) - fields_for(*args, &proc) - end - - def labelled_remote_form_for(*args, &proc) - ActiveSupport::Deprecation.warn "ApplicationHelper#labelled_remote_form_for is deprecated and will be removed in Redmine 2.2." - args << {} unless args.last.is_a?(Hash) - options = args.last - options.merge!({:builder => Redmine::Views::LabelledFormBuilder, :remote => true}) - form_for(*args, &proc) - end - - def error_messages_for(*objects) - html = "" - # modified by fq - if objects.first.is_a?(Array) - objects = objects.first - end - # end - if objects != nil - objects = objects.map {|o| o.is_a?(String) ? instance_variable_get("@#{o}") : o}.compact - errors = objects.map {|o| o.errors.full_messages}.flatten - if errors.any? - html << "
    \n" - end - end - html.html_safe - end - - def delete_link(url, options={}) - options = { - :method => :delete, - :data => {:confirm => l(:text_are_you_sure)}, - :class => 'icon icon-del' - }.merge(options) - - link_to l(:button_delete), url, options - end - - def update_status_link(user) - url = {:controller => 'users', :action => 'update', :id => user, :page => params[:page], :status => params[:status], :tab => nil} - - if user.locked? - link_to "解锁", url.merge(:user => {:status => User::STATUS_ACTIVE}), :method => :put, :class => 'mr10 link-color-blue' - elsif user.registered? - link_to "激活", url.merge(:user => {:status => User::STATUS_ACTIVE}), :method => :put, :class => 'mr10 link-color-blue' - elsif user != User.current - link_to "加锁", url.merge(:user => {:status => User::STATUS_LOCKED}), :method => :put, :class => 'mr10 link-color-blue' - end - end - - - def delete_version_link(url, options={}) - options = { - :method => :delete, - :data => {:confirm => l(:text_are_you_sure)}, - :class => 'icon icon-del' - }.merge(options) - - link_to "", url, options - end - - def delete_link_version(url, options={}) - options = { - :method => :delete, - :data => {:confirm => l(:text_are_you_sure)}, - :class => 'c_purple' - }.merge(options) - - link_to l(:button_delete), url, options - end - - - - def delete_new_link(url, options={}) - options = { - :method => :delete, - :data => {:confirm => l(:text_are_you_sure)}, - :class => "c_purple" - }.merge(options) - - link_to l(:button_delete), url, options - end - - def preview_link(url, form, target='preview', options={}) - content_tag 'a', l(:label_preview), { - :href => "#", - :onclick => %|submitPreview("#{escape_javascript url_for(url)}", "#{escape_javascript form}", "#{escape_javascript target}"); return false;|, - :accesskey => accesskey(:preview) - }.merge(options) - end - - def link_to_function(name, function, html_options={}) - content_tag(:a, name, {:href => '#', :onclick => "#{function}; return false;"}.merge(:class => "BlueCirBtnMini ml10",:style => "display:inline-block; height:20px; line-height:20px;")) - end - - def link_to_function_none(name, function, html_options={}) - content_tag(:a, name, {:href => '#', :onclick => "#{function}; return false;"}.merge(:style => "display:inline-block; height:20px; line-height:20px;")) - end - - # Helper to render JSON in views - def raw_json(arg) - arg.to_json.to_s.gsub('/', '\/').html_safe - end - - def back_url - url = params[:back_url] - if url.nil? && referer = request.env['HTTP_REFERER'] - url = CGI.unescape(referer.to_s) - end - url - end - - def back_url_hidden_field_tag - url = back_url - hidden_field_tag('back_url', url, :id => nil) unless url.blank? - end - - def check_all_links(form_name) - link_to_function_none(l(:button_check_all), "checkAll('#{form_name}', true)") + " ".html_safe + " | "+ " ".html_safe + - link_to_function_none(l(:button_uncheck_all), "checkAll('#{form_name}', false)") - end - - # 本次修改,修改为只显示关闭的所占%比 - def progress_bar(pcts, options={}) - pcts = [pcts] unless pcts.is_a?(Array) - pcts = pcts.collect(&:round) - # pcts[1] = pcts[1] + pcts[0] - pcts << (100 - pcts[0]) - width = options[:width] || '100px;' - legend = options[:legend] || '' - content_tag('span', - content_tag('tr', - (pcts[0] > 0 ? content_tag('span', '', :style => "width: #{pcts[0]}%;", :class => 'roadmap_progressbar_inner', :title => "已关闭:#{pcts[0]}%") : ''.html_safe) #+ - # (pcts[1] > 0 ? content_tag('td', '', :style => "width: #{pcts[1]}%;", :class => 'done', :title => "开发中:#{pcts[1]}%") : ''.html_safe) + - #(pcts[1] > 0 ? content_tag('span', '', :style => "width: #{pcts[1]}%;", :class => 'roadmap_progressbar ml5', :title => "未完成:#{pcts[1]}%") : ''.html_safe), :style => "width: #{width}" - ), :class => 'roadmap_progressbar ml5').html_safe - # + content_tag('p', legend, :class => 'percent').html_safe - end - - def checked_image(checked=true) - if checked - image_tag 'toggle_check.png' - end - end - - def context_menu(url) - unless @context_menu_included - content_for :header_tags do - javascript_include_tag('context_menu') + - stylesheet_link_tag('context_menu') - end - if l(:direction) == 'rtl' - content_for :header_tags do - stylesheet_link_tag('context_menu_rtl') - end - end - @context_menu_included = true - end - javascript_tag "contextMenuInit('#{ url_for(url) }')" - end - - def calendar_for(field_id,start_day=nil) - include_calendar_headers_tags(start_day) - javascript_tag("$(function() { $('##{field_id}').datepicker(datepickerOptions); });") - end - - def include_calendar_headers_tags(start_day=nil) - if start_day.nil? - unless @calendar_headers_tags_included - @calendar_headers_tags_included = true - content_for :header_tags do - start_of_week = Setting.start_of_week - start_of_week = l(:general_first_day_of_week, :default => '1') if start_of_week.blank? - # Redmine uses 1..7 (monday..sunday) in settings and locales - # JQuery uses 0..6 (sunday..saturday), 7 needs to be changed to 0 - start_of_week = start_of_week.to_i % 7 - - tags = javascript_tag( - "var datepickerOptions={dateFormat: 'yy-mm-dd', firstDay: #{start_of_week}, " + - "showOn: 'button', buttonImageOnly: true, buttonImage: '" + - path_to_image('/images/public_icon.png') + - "', showButtonPanel: true, showWeek: true, showOtherMonths: true, selectOtherMonths: true};") - jquery_locale = l('jquery.locale', :default => current_language.to_s) - unless jquery_locale == 'en' - tags << javascript_include_tag("i18n/jquery.ui.datepicker-#{jquery_locale}.js") - end - tags - end - end - else - unless @calendar_headers_tags_included - @calendar_headers_tags_included = true - content_for :header_tags do - start_of_week = Setting.start_of_week - start_of_week = l(:general_first_day_of_week, :default => '1') if start_of_week.blank? - # Redmine uses 1..7 (monday..sunday) in settings and locales - # JQuery uses 0..6 (sunday..saturday), 7 needs to be changed to 0 - start_of_week = start_of_week.to_i % 7 - - tags = javascript_tag( - "var datepickerOptions={dateFormat: 'yy-mm-dd',minDate: new Date(), firstDay: #{start_of_week}, " + - "showOn: 'button', buttonImageOnly: true, buttonImage: '" + - path_to_image('/images/public_icon.png') + - "', showButtonPanel: true, showWeek: true, showOtherMonths: true, selectOtherMonths: true, onClose: function(dateText, inst) {TimeClose(dateText,inst);}, beforeShow : function(input){TimeBeforeShow(input);} };") - jquery_locale = l('jquery.locale', :default => current_language.to_s) - unless jquery_locale == 'en' - tags << javascript_include_tag("i18n/jquery.ui.datepicker-#{jquery_locale}.js") - end - tags - end - end - end - - end - - # Overrides Rails' stylesheet_link_tag with themes and plugins support. - # Examples: - # stylesheet_link_tag('styles') # => picks styles.css from the current theme or defaults - # stylesheet_link_tag('styles', :plugin => 'foo) # => picks styles.css from plugin's assets - # - def stylesheet_link_tag(*sources) - options = sources.last.is_a?(Hash) ? sources.pop : {} - plugin = options.delete(:plugin) - sources = sources.map do |source| - if plugin - "/plugin_assets/#{plugin}/stylesheets/#{source}" - elsif current_theme && current_theme.stylesheets.include?(source) - current_theme.stylesheet_path(source) - else - source - end - end - super sources, options - end - - # Overrides Rails' image_tag with themes and plugins support. - # Examples: - # image_tag('image.png') # => picks image.png from the current theme or defaults - # image_tag('image.png', :plugin => 'foo) # => picks image.png from plugin's assets - # - def image_tag(source, options={}) - if plugin = options.delete(:plugin) - source = "/plugin_assets/#{plugin}/images/#{source}" - elsif current_theme && current_theme.images.include?(source) - source = current_theme.image_path(source) - end - super source, options - end - - # Overrides Rails' javascript_include_tag with plugins support - # Examples: - # javascript_include_tag('scripts') # => picks scripts.js from defaults - # javascript_include_tag('scripts', :plugin => 'foo) # => picks scripts.js from plugin's assets - # - def javascript_include_tag(*sources) - options = sources.last.is_a?(Hash) ? sources.pop : {} - - @sources ||= [] - sources = sources.delete_if do|source| - @sources.include?(source) - end - @sources += sources - - if plugin = options.delete(:plugin) - sources = sources.map do |source| - if plugin - "/plugin_assets/#{plugin}/javascripts/#{source}" - else - source - end - end - end - - if sources && !sources.empty? - super(sources, options) - else - '' - end - end - - def content_for(name, content = nil, &block) - @has_content ||= {} - @has_content[name] = true - super(name, content, &block) - end - - def has_content?(name) - (@has_content && @has_content[name]) || false - end - - def sidebar_content? - has_content?(:sidebar) || view_layouts_base_sidebar_hook_response.present? - end - - def view_layouts_base_sidebar_hook_response - @view_layouts_base_sidebar_hook_response ||= call_hook(:view_layouts_base_sidebar) - end - - def email_delivery_enabled? - !!ActionMailer::Base.perform_deliveries - end - - # Returns the avatar image tag for the given +user+ if avatars are enabled - # +user+ can be a User or a string that will be scanned for an email address (eg. 'joe ') - def avatar(user, options = { }) - if Setting.gravatar_enabled? - options.merge!({:ssl => (request && request.ssl?), :default => Setting.gravatar_default}) - email = nil - if user.respond_to?(:mail) - email = user.mail - elsif user.to_s =~ %r{<(.+?)>} - email = $1 - end - return gravatar(email.to_s.downcase, options) unless email.blank? rescue nil - #options ={"class" => ["avatar2"],"width" =>["80px"],"height" =>["80px"]} - #return image_tag url_to_avatar(user), options - else - '' - end - end - - def sanitize_anchor_name(anchor) - if ''.respond_to?(:encoding) || RUBY_PLATFORM == 'java' - anchor.gsub(%r{[^\s\-\p{Word}]}, '').gsub(%r{\s+(\-+\s*)?}, '-') - else - # TODO: remove when ruby1.8 is no longer supported - anchor.gsub(%r{[^\w\s\-]}, '').gsub(%r{\s+(\-+\s*)?}, '-') - end - end - - # Returns the javascript tags that are included in the html layout head - def javascript_heads - tags = javascript_include_tag('jquery-1.8.3-ui-1.9.2-ujs-2.0.3', 'jquery.colorbox-min', 'baiduTemplate') - unless User.current.pref.warn_on_leaving_unsaved == '0' - tags << "\n".html_safe + javascript_tag("$(window).load(function(){ warnLeavingUnsaved('#{escape_javascript l(:text_warn_on_leaving_unsaved)}'); });") - end - tags - end - def javascript_edu_index_heads - tags = javascript_include_tag('jquery-1.8.3-ui-1.9.2-ujs-2.0.3', 'application') - unless User.current.pref.warn_on_leaving_unsaved == '0' - tags << "\n".html_safe + javascript_tag("$(window).load(function(){ warnLeavingUnsaved('#{escape_javascript l(:text_warn_on_leaving_unsaved)}'); });") - end - tags - end - - # 临时本地版 - def javascript_heads_local - tags = javascript_include_tag('jquery-1.8.3-ui-1.9.2-ujs-2.0.3', 'jquery.colorbox-min') - unless User.current.pref.warn_on_leaving_unsaved == '0' - tags << "\n".html_safe + javascript_tag("$(window).load(function(){ warnLeavingUnsaved('#{escape_javascript l(:text_warn_on_leaving_unsaved)}'); });") - end - tags - end - - def hubspot_head - tags = javascript_include_tag('hubspot/messenger.min', 'hubspot/messenger-theme-future') - tags << stylesheet_link_tag('hubspot/messenger', 'hubspot/messenger-theme-future', 'hubspot/messenger-theme-flat') - end - - def bootstrap_head - tags = stylesheet_link_tag('bootstrap/bootstrap.min', 'bootstrap/bootstrap-theme.min') - tags << javascript_include_tag('bootstrap/affix') - tags << javascript_include_tag('bootstrap/alert') - tags << javascript_include_tag('bootstrap/button') - tags << javascript_include_tag('bootstrap/carousel') - tags << javascript_include_tag('bootstrap/collapse') - tags << javascript_include_tag('bootstrap/dropdown') - tags << javascript_include_tag('bootstrap/modal') - tags << javascript_include_tag('bootstrap/popover') - tags << javascript_include_tag('bootstrap/scrollspy') - tags << javascript_include_tag('bootstrap/tab') - tags << javascript_include_tag('bootstrap/tooltip') - tags << javascript_include_tag('bootstrap/transition') - tags - end - - def favicon - "".html_safe - end - - def robot_exclusion_tag - ''.html_safe - end - - # Returns true if arg is expected in the API response - def include_in_api_response?(arg) - unless @included_in_api_response - param = params[:include] - @included_in_api_response = param.is_a?(Array) ? param.collect(&:to_s) : param.to_s.split(',') - @included_in_api_response.collect!(&:strip) - end - @included_in_api_response.include?(arg.to_s) - end - - # Returns options or nil if nometa param or X-Redmine-Nometa header - # was set in the request - def api_meta(options) - if params[:nometa].present? || request.headers['X-Redmine-Nometa'] - # compatibility mode for activeresource clients that raise - # an error when unserializing an array with attributes - nil - else - options - end - end - - # Add by Tao - def url_to_avatar(source) - source = nil if source.kind_of?(String) - get_avatar(source) - end - # Endof Tao's code - - # cxt - # 获取认证照片 - def url_to_auth_img(user_id, type) - if File.exist?(disk_auth_filename("UserAuthentication",user_id,type)) - File.join(relative_path,avatar_directory("UserAuthentication"), auth_filename(user_id,type)) - else - File.join(relative_path,avatar_directory("UserAuthentication"),type) - end - end - - def url_to_coop_img(type) - File.join(relative_path,avatar_directory('type'),"*") - end - - # 讨论区的平台icon ["Java", "C", "C++", "Python2.7", "Python3.6", "MySQL/Java", "Html", "JFinal", "Docker", "Ethereum", "Dynamips", "MachineLearning", "Verilog","Spark","MySQL/Python3.6","PHP","PHP/Web","Hadoop", "Golang","Android","Matlab","Shell"] - - def url_to_platform_icon language - case language - when 'Python2.7', 'Python3.6' - File.join(relative_path,avatar_directory("Platform"), 'Python') - when 'MySQL/Java', 'MySQL/Python3.6' - File.join(relative_path,avatar_directory("Platform"), 'MySQL') - when 'PHP/Web' - File.join(relative_path,avatar_directory("Platform"), 'PHP') - when 'C#' - File.join(relative_path,avatar_directory("Platform"), 'Cxp') - when 'C/C++' - File.join(relative_path,avatar_directory("Platform"), 'Cjia') - when 'Angular2+' - File.join(relative_path,avatar_directory("Platform"), 'Angular2jia') - else - File.join(relative_path,avatar_directory("Platform"), language.nil? ? "" : language) - end - end - - def identity_authentication_status user - authorization = user.apply_actions.where(:container_type => "TrialAuthorization").last - case user.try(:certification) - when 0 - if authorization.try(:status) == 0 - "处理中" - else - "未授权" - end - when 1 - "已授权" - when 2 - "被拒绝" - end - end - - def user_certification_status user - status = "" - if user.authentication - status = "已实名认证" - else - apply_auth = ApplyUserAuthentication.where(:user_id => user.id, :auth_type => 1).last - if apply_auth && apply_auth.status == 0 - status = "实名认证中" - elsif apply_auth && apply_auth.status == 2 - status = "实名认证未通过" - else - status = "未实名认证" - end - end - end - - def pro_certification_status user - status = "" - if user.professional_certification - status = "已职业认证" - else - apply_auth = ApplyUserAuthentication.where(:user_id => user.id, :auth_type => 2).last - if apply_auth && apply_auth.status == 0 - status = "职业认证中" - elsif apply_auth && apply_auth.status == 2 - status = "职业认证未通过" - else - status = "未职业认证" - end - end - end - - def shixun_authentication_status shixun - case shixun.try(:status) - when 0,nil - "编辑中" - when 1 - "待审核" - when 2 - "已发布" - when 3 - "已关闭" - end - end - - def date_format_local(time) - date = time.strftime("%Y年%m月%d日") - end - - #当TAG数量过多时,更多链接 - #1代表是user类型 2代表是project类型 3代表是issue类型 4代表需求 9代表课程 - def more_tags id,object_flag - a= 1 - case object_flag - when "1" - s = link_to l(:label_more_tags),:controller => "users", :action => "show", :id => id - when "2" - s = link_to l(:label_more_tags),:controller => "projects", :action => "show", :id => id - when "3" - s = link_to l(:label_more_tags),:controller => "issues", :action => "show", :id => id - when "4" - s = link_to l(:label_more_tags),:controller => "bids", :action => "show", :id => id - when "9" - s = link_to l(:label_more_tags),:controller => "courses", :action => "show", :id => id - end - s - end - - def get_user_identity identity - s = "" - case identity - when 0 - s = '教师' - when 1 - s = '学生' - when 2 - s = '组织' - when 3 - s= '开发者' - else - s = '学生' - end - s - end - - # 获取issue类型 - def get_issue_type_new tracker_id - case tracker_id - when 1 - "缺陷" - when 2 - "功能" - when 3 - "支持" - when 4 - "任务" - when 5 - "周报" - end - end - - def get_memo - @new_memo = Memo.new - @public_forum = Forum.find(1) rescue ActiveRecord::RecordNotFound - end - - #获取用户未过期的课程 - def get_user_course user - courses_doing = [] - user.courses.select("courses.*,(SELECT MAX(created_at) FROM `course_activities` WHERE course_activities.course_id = courses.id) AS a").order("a desc").each do |course| - if !course_endTime_timeout?(course) - courses_doing.push course - end - end - courses_doing - end - - def attachment_history_candown attachment_history - if attachment_history.container_type == "Course" - course = Course.find(attachment_history.container_id) - candown = User.current.member_of_course?(course) || (course.is_public && attachment_history.is_public == 1) - elsif attachment_history.container_type == "Project" - project = Project.find(attachment_history.container_id) - candown = User.current.member_of?(project) || (project.is_public && attachment_history.is_public == 1) - elsif attachment_history.container_type == "OrgSubfield" - org = OrgSubfield.find(attachment_history.container_id).organization - candown = User.current.member_of_org?(org) || (org.organization.is_public && attachment_history.is_public == 1 && (User.current.logged? || org.organization.allow_guest_download?)) - end - end - - def resource_bank_candown resource,type - candown = false - if resource.is_public - candown = true - end - if type == 'syllabus' - candown = syllabus_course_member(User.current, resource.course) || User.current.admin? - end - candown - end - - # 课程某个班级的成员 - def syllabus_course_member user, course - result = false - syllabus = course.syllabus - if syllabus - syllabus.courses.each do |course| - if user.member_of_course?(course) - result = true - return result - end - end - end - result - end - - def attachment_candown attachment - candown = false - if attachment.container - if attachment.container.class.to_s=="PhoneAppVersion" - candown = true - elsif attachment.container.class.to_s != "HomeworkAttach" && attachment.container.class.to_s != "StudentWork" && attachment.container.class.to_s != "ContestantWork" && (attachment.container.has_attribute?(:project) || attachment.container.has_attribute?(:project_id)) && attachment.container.project - project = attachment.container.project - candown= User.current.member_of?(project) || (project.is_public && attachment.is_public == 1) - elsif attachment.container.is_a?(Project) - project = attachment.container - candown = User.current.member_of?(project) || (attachment.is_public == 1) || attachment.get_status_by_attach(User.current.id) == 2 - elsif (attachment.container.has_attribute?(:board) || attachment.container.has_attribute?(:board_id)) && attachment.container.board && - attachment.container.board.project - project = attachment.container.board.project - candown = User.current.member_of?(project) || (project.is_public && attachment.is_public == 1) - elsif (attachment.container.has_attribute?(:course) ||attachment.container.has_attribute?(:course_id) ) && attachment.container.course - course = attachment.container.course - candown = User.current.member_of_course?(course) || (attachment.is_public == 1) || attachment.get_status_by_attach(User.current.id) == 2 - elsif attachment.container.is_a?(Course) - course = attachment.container - candown= User.current.member_of_course?(course) || (attachment.is_public == 1) || attachment.get_status_by_attach(User.current.id) == 2 - elsif attachment.container.is_a?(OrgSubfield) - org = attachment.container.organization - candown = User.current.member_of_org?(org) || ((attachment.is_public == 1 || attachment.get_status_by_attach(User.current.id) == 2) && org.allow_guest_download == true) - elsif attachment.container.is_a?(OrgDocumentComment) - org = attachment.container.organization - candown = org.allow_guest_download || User.current.member_of_org?(org) || (org.is_public && attachment.is_public == 1) - elsif (attachment.container.has_attribute?(:board) || attachment.container.has_attribute?(:board_id)) && attachment.container.board && - attachment.container.board.course - course = attachment.container.board.course - candown= User.current.member_of_course?(course) || (course.is_public==1 && attachment.is_public == 1) - elsif attachment.container.class.to_s=="Organization" - candown = true - elsif attachment.container.class.to_s=="HomeworkAttach" - candown = true - elsif attachment.container.class.to_s=="StudentWorksScore" - candown = true - elsif attachment.container.class.to_s=="StudentWork" - candown = true - elsif attachment.container.class.to_s=="Contest" - candown = true - elsif attachment.container.class.to_s=="Work" - candown = true - elsif attachment.container.class.to_s=="ContestantWork" - candown = true - elsif attachment.container.class.to_s=="HomeworkBank" - candown = true - elsif attachment.container.class.to_s=="BlogComment" #博客资源允许下载 - candown = true - elsif attachment.container.class.to_s=="Memo" #论坛资源允许下载 - candown = true - elsif attachment.container.class.to_s=="Syllabus" #论坛资源允许下载 - candown = true - elsif attachment.container.class.to_s=="Competition" #竞赛资源允许下载 - candown = true - elsif attachment.container.class.to_s=="Career" #职业路径资源允许下载 - candown = true - elsif attachment.container_type == "Inform" #竞赛通知公告允许下载 - candown = true - elsif attachment.container.class.to_s == "User" - candown = (attachment.is_public == 1 || attachment.is_public == true || attachment.author_id == User.current.id) - elsif attachment.container_type == "Bid" && attachment.container && attachment.container.courses - course = attachment.container.courses.first - candown = User.current.member_of_course?(attachment.container.courses.first) || (course.is_public == 1 && attachment.is_public == 1) - else - candown = (attachment.is_public == 1 || attachment.is_public == true) - end - else - if attachment.container_type == "MarkDown" || attachment.container_type.nil? || attachment.container_type == 'Subject' || attachment.container_type == "Shixun" || attachment.container_type == "Memo" || attachment.container_type == "Career" || attachment.container_type == "Exercise" || attachment.container_type == "ExerciseBank" - candown = true - end - end - candown - end - - def project_type_link(text, value) - if value == 1 - link_to "#{text}".html_safe,"javascript:void(0)" ,:onClick => "show_window();", :class => "pr_join_a",:id => "setting_project_type" - elsif value == 2 - link_to "#{text}".html_safe,"javascript:void(0)" ,:onClick => "show_window();", :class => "pr_join_a",:id => "setting_project_type" - else - link_to "#{text}".html_safe,"javascript:void(0)" ,:onClick => "show_window();", :class => "pr_join_a",:id => "setting_project_type" - end - - end - - #如果学生作品被打分后修改,应该给老师提示 - def send_message_to_teacher student_work - if StudentWork === student_work - student_work_scores = student_work.student_works_scores.where("reviewer_role != 3") - if student_work_scores.any? - student_work.update_column('re_commit', 1) - course = student_work.homework_common.course - course.teachers.where(:user_id => student_work_scores.map(&:user_id).uniq).each do|mem| - student_work.tidings << Tiding.new(:user_id => mem.user_id, :trigger_user_id => student_work.user_id, :container_id => student_work.id, :container_type => "StudentWork", :parent_container_id => student_work.homework_common_id, :parent_container_type => "HomeworkCommon", - :belong_container_id => course.id, :belong_container_type => "Course", :viewed => 0, :tiding_type => "HomeworkCommon", :extra => "resubmit") - end - end - end - end - - private - - def wiki_helper - helper = Redmine::WikiFormatting.helper_for(Setting.text_formatting) - extend helper - return self - end - - def link_to_content_update(text, url_params = {}, html_options = {}) - link_to(text, url_params, html_options) - end - -#added by nie -# Display watcher picture - def show_more_watchers?(obj) - if User.watched_by(obj.id).count > 6 - return true - else - return false - end - end - - def show_watcher_profile(obj) - count = 0 - html = '' - if User.watched_by(obj.id).count == 0 - html << (content_tag "span", l(:label_no_current_watchers)) - end - for user in User.watched_by(obj.id) - html << (link_to image_tag(url_to_avatar(user), :class => "avatar"), user_path(user), :class => "avatar", :title => "#{user.name}") - count = count + 1 - if count >= 12 - break - end - end - html.html_safe - end - -#display bid project - def show_more_bid_project?(bid) - if bid.projects.where('is_public = 1').count > 12 - return true - else - return false - end - end - - def show_bid_project(bid) - html = '' - if bid.projects.where('is_public = 1').count == 0 - html << (content_tag "p", l(:label_no_bid_project), :class => "font_lighter") - else - bid.projects.where('is_public = 1').take(12).each do |project| - html << (link_to image_tag(url_to_avatar(project), :class => "avatar", :title => project.name), project_path(project), :class => "avatar") - end - end - html.html_safe - end - - def show_bid_fans_picture(obj) - html = '' - if obj.watcher_users.count == 0 - html << (content_tag "span", l(:label_project_no_follow)) - else - obj.watcher_users.take(12).each do |user| - html << (link_to image_tag(url_to_avatar(user), :class => "avatar"), user_path(user), :class => "avatar", :title => user.name) - end - end - html.html_safe - end - -#display contest project - def show_more_contest_project?(contest) - if contest.projects.where('is_public = 1').count > 12 - return true - else - return false - end - end - - def show_more_contest_softapplication?(contest) - if contest.softapplications.where('is_public = 1').count > 12 - return true - else - return false - end - end - - def show_contest_project(bid) - html = '' - if contest.projects.where('is_public = 1').count == 0 - html << (content_tag "p", l(:label_no_bid_project), :class => "font_lighter") - else - contest.projects.where('is_public = 1').take(12).each do |project| - html << (link_to image_tag(url_to_avatar(project), :class => "avatar", :title => project.name), project_path(project), :class => "avatar") - end - end - html.html_safe - end - - def show_contest_project(contest) - html = '' - if contest.projects.where('is_public = 1').count == 0 - html << (content_tag "p", l(:label_no_bid_project), :class => "font_lighter") - else - contest.projects.where('is_public = 1').take(12).each do |project| - html << (link_to image_tag(url_to_avatar(project), :class => "avatar", :title => project.name), project_path(project), :class => "avatar") - end - end - html.html_safe - end - - def show_contest_softapplication(contest) - html = '' - if contest.softapplications.where('is_public = 1').count == 0 - html << (content_tag "p", l(:label_no_contest_softapplication), :class => "font_lighter") - else - contest.softapplications.where('is_public = 1').take(12).each do |softapplication| - html << (link_to image_tag(url_to_avatar(project), :class => "avatar", :title => project.name), project_path(project), :class => "avatar") - end - end - html.html_safe - end - - def show_contest_fans_picture(obj) - html = '' - if obj.watcher_users.count == 0 - html << (content_tag "span", l(:label_project_no_follow)) - else - obj.watcher_users.take(12).each do |user| - html << (link_to image_tag(url_to_avatar(user), :class => "avatar"), user_path(user), :class => "avatar", :title => user.name) - end - end - html.html_safe - end - -#display fans picture - def show_more_fans?(obj) - if obj.watcher_users.count > 12 - return true - else - return false - end - end - - def show_fans_picture(obj) - html = '' - if obj.watcher_users.count == 0 - html << (content_tag "span", l(:label_no_current_fans)) - else - obj.watcher_users.take(12).each do |user| - html << (link_to image_tag(url_to_avatar(user), :class => "avatar"), user_path(user), :class => "avatar", :title => user.name) - end - end - html.html_safe - end - - # added by bai - def show_more_participate?(obj) - if obj.join_in_contests.count > 12 - return true - else - return false - end - end - - def show_participate_picture(obj) - html = '' - count = 0 - if obj.join_in_contests.count == 0 - html << (content_tag "span", l(:label_no_current_participate)) - end - for temp in obj.join_in_contests - html << (link_to image_tag(url_to_avatar(temp.user), :class => "avatar"), user_path(temp.user), :class => "avatar", :title => "#{temp.user.name}") - count = count + 1 - if count >= 12 - break - end - end - html.html_safe - end - -#end - -# add by huang - def show_watcher_list(user) - html = '' - count = 0 - for user in User.watched_by(user.id) - html << (link_to image_tag(url_to_avatar(user), :class => "avatar"), user_path(user), :class => "avatar", :title => "#{user.name}") - count = count + 1 - if count >= 12 - break - end - end - html.html_safe - end -# end - -#added by william - def get_fans_num(user) - user.watcher_users.count - end -#end - - - def hadcommittedhomework(cur,curb) - bid = Bid.find_by_id(curb) - return true if bid.nil? - - case bid.homework_type - when Bid::HomeworkFile - attaches = HomeworkAttach.where(bid_id: curb) - attaches.map(&:user_id).include? cur - when Bid::HomeworkProject - attaches = BidingProject.where(user_id: User.current, bid_id: bid) - attaches.count > 0 # > 0 则有提交记录 - else - true - end - - end - - def render_dynamic_nav - home_link = link_to l(:field_homepage), {:controller => 'welcome', :action => 'index'} - home_link = "
  • " << home_link << "
  • " - # bootstrap_render_dynamic_nav - content_tag :ul, (home_link.html_safe+bootstrap_render_dynamic_nav) - end - - def bootstrap_render_dynamic_nav - hidden_non_project = Setting.find_by_name("hidden_non_project") - visiable = !(hidden_non_project && hidden_non_project.value == "0") - - main_course_link = link_to l(:label_course_practice), {:controller => 'welcome', :action => 'index', :host => Setting.host_course} - main_project_link = link_to l(:label_project_deposit), {:controller => 'welcome', :action => 'index', :host => Setting.host_name} - main_contest_link = link_to l(:label_contest_innovate), {:controller => 'welcome', :action => 'index', :host => Setting.host_contest} - - # course_all_course_link = link_to l(:label_course_all), {:controller => 'courses', :action => 'index'} - course_teacher_all_link = link_to l(:label_teacher_all), {:controller => 'users', :action => 'index', :role => 'teacher', :host => Setting.host_course} - # courses_link = link_to l(:label_course_practice), {:controller => 'courses', :action => 'index'} - #users_link = link_to l(:label_software_user), {:controller => 'users', :action => 'index', :host => Setting.host_user} - # contest_link = link_to l(:label_contest_innovate), {:controller => 'contests', :action => 'index'} - # bids_link = link_to l(:label_requirement_enterprise), {:controller => 'bids', :action => 'index'} - forum_link = link_to l(:label_forum_all), {:controller => "forums", :action => "index"} - stores_link = link_to l(:label_stores_index), {:controller => 'stores', :action=> 'index'} - school_all_school_link = link_to l(:label_school_all), {:controller => 'school', :action => 'index'} - project_new_link = link_to l(:label_project_new), {:controller => 'projects', :action => 'new', :host => Setting.host_name} - # project_mine_link = link_to l(:label_my_project), {:controller => 'users', :action => 'user_projects', :host => Setting.host_name} - - #@nav_dispaly_project_label - nav_list = Array.new - nav_list.push(school_all_school_link) if @nav_dispaly_course_all_label && @show_course == 1 && visiable - # nav_list.push(course_all_course_link) if @nav_dispaly_course_all_label && @show_course == 1 - nav_list.push(course_teacher_all_link) if @nav_dispaly_teacher_all_label && @show_course == 1 && visiable - - nav_list.push(main_project_link) if @nav_dispaly_main_project_label - nav_list.push(main_course_link) if @nav_dispaly_main_course_label && @show_course == 1 && visiable - nav_list.push(main_contest_link) if @nav_dispaly_main_contest_label && @show_contest == 1 && visiable - - nav_list.push(courses_link) if @nav_dispaly_course_label && @show_course == 1 && visiable - nav_list.push(project_new_link) if @nav_dispaly_project_label - # nav_list.push(project_mine_link) if @nav_dispaly_main_project_label - # nav_list.push(projects_link) if @nav_dispaly_project_label - #nav_list.push(users_link) if @nav_dispaly_user_label - # nav_list.push(contest_link) if @nav_dispaly_contest_label && @show_contest == 1 - nav_list.push(bids_link) if @nav_dispaly_bid_label && visiable - nav_list.push(forum_link) if @nav_dispaly_forum_label && visiable - nav_list.push(stores_link) if @nav_dispaly_store_all_label && visiable - - content_li = '' - nav_list.collect do |nav_item| - content_li << content_tag(:li, nav_item, :class => 'topnav_a fl') - end - content_li.html_safe - end - - def current_user - User.current - end - - # def hadcommittedforcontest(curu) - # message = JournalsForMessage.find_by_sql("select * from journals_for_messages where jour_type = 'Softapplication' ") - # message.each do |createmessage| - # if createmessage.user_id == curu - # return true - # end - # end - # end - - # 获取用户的认证状态 - def get_authentication_status user - result = '' - if user.authentication - result += '
  • ' - else - apply_auth = ApplyUserAuthentication.where(:user_id => user.id, :auth_type => 1).last - if apply_auth && apply_auth.status == 0 - result += '
  • ' - else - result += '
  • ' - end - end - if user.professional_certification - result += '
  • ' - else - apply_auth = ApplyUserAuthentication.where(:user_id => user.id, :auth_type => 2).last - if apply_auth && apply_auth.status == 0 - result += '
  • ' - else - result += '
  • ' - end - end - return result.html_safe - end - - def footer_logo(ul_class=nil, li_class=nil) - logos = [] - logos.push(link_to image_tag('/images/footer_logo/nudt.png',:alt=>"nudt"),"http://www.nudt.edu.cn/special.asp?classid=12" ) - logos.push(link_to image_tag('/images/footer_logo/peking_eecs.png', :alt=>"peking_eecs"), "http://www.sei.pku.edu.cn/" ) - logos.push(link_to image_tag('/images/footer_logo/buaa_scse.png', :alt=>"buaa_scse"), "http://scse.buaa.edu.cn/" ) - logos.push(link_to image_tag('/images/footer_logo/iscas.png', :alt=>"iscas"), "http://www.iscas.ac.cn" ) - logos.push(link_to image_tag('/images/footer_logo/inforbus.png', :alt=>"inforbus"), "http://www.inforbus.com" ) - - logos.collect! { |logo| - content_tag(:li, logo.html_safe, :class => li_class.to_s) - } - - content_tag(:ul, logos.join("").html_safe, :class => ul_class.to_s).html_safe - end - - def sort_homework_path(bid, sort, direction) - case self.action_name - when 'show_courseEx' - get_not_batch_homework_homework_attach_index_path(bid_id: bid.id, sort: sort, direction: 'asc') - when 'get_not_batch_homework' - get_not_batch_homework_homework_attach_index_path(bid_id: bid.id, sort: sort, direction: direction) - when 'get_batch_homeworks' - get_batch_homeworks_homework_attach_index_path(bid_id: bid.id, sort: sort, direction: direction) - when 'get_homeworks' - get_homeworks_homework_attach_index_path(bid_id: bid.id, sort: sort, direction: direction) - else - '#' - end - end - - def anonymous_comment_link(bid, course) - link = case bid.comment_status - when 0 - confirm_info = "开启匿评后学生将不能对作品进行提交、修改、删除等操作\n" - confirm_info += anonymous_comment_notice(bid,course) - confirm_info += '是否确定开启匿评?' - link_to '启动匿评', start_anonymous_comment_bid_path(bid), id: "#{bid.id}_start_anonymous_comment", remote: true, :confirm => confirm_info, disable_with: '加载中...' - when 1 - confirm_info = "关闭匿评后所有同学将不能继续进行匿评,且将公开已提交作品列表\n" - confirm_info += anonymous_comment_notice(bid,course) - confirm_info += '是否确定关闭匿评?' - link_to '关闭匿评', stop_anonymous_comment_bid_path(bid), id: "#{bid.id}_stop_anonymous_comment", remote: true, :confirm => confirm_info - when 2 - '匿评结束' - end - content_tag('span', link, id: "#{bid.id}_anonymous_comment") - end - - def anonymous_comment_notice(bid, course) - case bid.comment_status - when 0 - @student_size ||= searchStudent(course).size - @homework_size = bid.homeworks.size - percent = @homework_size.to_f / (@student_size == 0 ? 1 : @student_size) - confirm_info = "目前#{@student_size}个学生,总共提交了#{@homework_size}份作品,占#{number_to_percentage(percent * 100, precision: 1)}\n" - when 1 - @homework_evaluations = 0 - bid.homeworks.map { |homework| @homework_evaluations += homework.homework_evaluations.count} - teachers = "(" - teacher_members = searchTeacherAndAssistant(course) - teacher_members.each do |member| - if member == teacher_members.last - teachers += member.user_id.to_s + ")" - else - teachers += member.user_id.to_s + "," - end - end - @has_evaluations = 0 - bid.homeworks.map { |homework| @has_evaluations += homework.rates(:quality).where("seems_rateable_rates.rater_id not in #{teachers}").count} - - percent = @has_evaluations.to_f / (@homework_evaluations == 0 ? 1 : @homework_evaluations) - confirm_info = "目前总共分配了#{@homework_evaluations}份匿评作品,已评价#{@has_evaluations}份作品,占#{number_to_percentage(percent * 100, precision: 1)}\n" - end - confirm_info - end - - def get_technical_title user - if user.user_extensions.technical_title == "Professor" || user.user_extensions.technical_title == "教授" - technical_title = l(:label_technicl_title_professor) - elsif user.user_extensions.technical_title == "Associate professor" || user.user_extensions.technical_title == "副教授" - technical_title = l(:label_technicl_title_associate_professor) - elsif user.user_extensions.technical_title == "Lecturer" || user.user_extensions.technical_title == "讲师" - technical_title = l(:label_technicl_title_lecturer) - elsif user.user_extensions.technical_title == "Teaching assistant" || user.user_extensions.technical_title == "助教" - technical_title = l(:label_technicl_title_teaching_assistant) - end - technical_title - end - - # 用户竞赛总数 - def user_contest_count - @user.favorite_contests.visible.where("is_delete =?", 0).count - end - - # 用户项目总数 - def user_project_count - @my_projects = @user.projects.visible.where("status != 9") - @my_project_total = @my_projects.count - end - - # 用户的课程总数 - def user_course_count - @my_course_count = @user.syllabuses.count - - sy_courses = @user.courses.visible.not_deleted - syllabus_ids = sy_courses.empty? ? '(-1)' : "(" + sy_courses.map{|course| !course.syllabus_id.nil? && course.syllabus_id}.join(",") + ")" - syllabus_members = SyllabusMember.where("user_id = #{@user.id}") - syllabus_member_ids = syllabus_members.empty? ? "(-1)" : "(" + syllabus_members.map{|syl_mem| syl_mem.syllabus_id}.join(',') + ")" - @join_syllabuses = Syllabus.where("(id in #{syllabus_ids} or id in #{syllabus_member_ids}) and user_id != #{@user.id}") - @my_joined_course_count = @join_syllabuses.count - - @user_course_total = @my_joined_course_count + @my_course_count - end - - # 用户发布的作业数 - def user_manage_homework_count - tea_courses = @user.courses.visible.not_deleted.select{|course| @user.has_teacher_role(course)} - tea_course_ids = tea_courses.map{|course| course.id} - @manage_homeworks = HomeworkCommon.where(:course_id => tea_course_ids).count - end - - # 用户收到的作业数 - def user_receive_homework_count - stu_courses = @user.courses.visible.not_deleted.select{|course| @user.has_student_role(course)} - stu_course_ids = stu_courses.empty? ? "(-1)" : "(" + stu_courses.map{|course| course.id}.join(',') + ")" - @homeworks = HomeworkCommon.where("course_id in #{stu_course_ids} and publish_time <= '#{Time.now}'").count - end - - # 用户发布的issue数 - def issues_author_is_self_count - Issue.where(:author_id => @user.id).count - end - - # 用户收到的issue数 - def issues_assigned_is_self_count - Issue.where( :assigned_to_id => @user.id ).count - end - - def get_user_roll user - technical_title = "" - case user.user_extensions.identity.to_s - when "0" - technical_title = get_technical_title user - when "1" - technical_title = l(:label_account_identity_student) - when "2" - technical_title = l(:label_account_identity_enterprise) - when "3" - technical_title = l(:label_account_identity_developer) - end - technical_title - end - - - def ie8? - request.env["HTTP_USER_AGENT"] =~ /MSIE 8.0/ - end - - - #获取指定资源列表的TAG的集合以及每个TAG的数量,降序排序 - def attachment_tag_list attachments - tag_list = Hash.new - attachments.each do |attachment| - attachment.tag_list.map{|tag| tag_list.has_key?(tag) ? tag_list[tag] = tag_list[tag] + 1 : tag_list[tag] = 1} - end - tag_list.sort {|a,b| b[1]<=>a[1]} - end - - #获取课程资源的TAG云 - def get_course_tag_list course - all_attachments = course.attachments - if User.current.admin? || User.current.allowed_to?(:as_teacher, course) - all_attachments = all_attachments.reorder("created_on desc") - elsif User.current.member_of_course?(course) - member = course.members.where(:user_id => User.current.id).first - if member.try(:course_group_id).to_i == 0 - all_attachments = all_attachments.where("is_publish = 1 and unified_setting = 1") - else - not_atta_ids = course.attachment_group_settings.where("course_group_id = #{member.try(:course_group_id)} and publish_time > '#{Time.now}'") - not_atta_ids = not_atta_ids.blank? ? "(-1)" : "(" + not_atta_ids.map(&:attachment_id).join(",") + ")" - all_attachments = all_attachments.where("is_publish = 1 and attachments.id not in #{not_atta_ids}") - end - else - all_attachments = all_attachments.where("is_publish = 1 and unified_setting = 1") - end - tag_list = attachment_tag_list all_attachments - tag_list - end - - # 获取项目资源的Tag云 - def get_project_tag_list project - all_attachments = project.attachments.select{|attachment| attachment.is_public? || - (attachment.container_type == "Project" && User.current.member_of?(project))|| - attachment.author_id == User.current.id - } - tag_list = attachment_tag_list all_attachments - tag_list - end - - # 获取项目fork成员数 - def project_fork_count - @forked_projects = Project.where(:forked_from_project_id => @project.id) - @forked_count = @forked_projects.count - end - - def get_org_subfield_tag_list org_subfield - all_attachments = org_subfield.attachments.select{|attachment| attachment.is_public? || - (attachment.container_type == "OrgSubfield" && User.current.member_of_org?(org_subfield.organization))|| - attachment.author_id == User.current.id - } - tag_list = attachment_tag_list all_attachments - tag_list - end - - #获取匿评相关连接代码 - def homework_anonymous_comment (homework, hw_status, user_activity_id = -1) - if homework.homework_detail_manual.comment_status == 0 || homework.end_time >= Time.now - link = link_to "启动匿评","javascript:void(0)", :class => "wpostOptionLink", :title => "作业截止日期之前不可以启动匿评" - elsif homework.student_works.has_committed.count >= 2 && homework.homework_detail_manual#作业份数大于2 - case homework.homework_detail_manual.comment_status - when 1 - link = link_to '启动匿评', Setting.protocol + "://" + Setting.host_name + "/homework_common/" + homework.id.to_s + "/alert_anonymous_comment?hw_status=" + hw_status.to_s + "&user_activity_id=" + user_activity_id.to_s, id: "#{homework.id}_start_anonymous_comment", remote: true, disable_with: '加载中...',:class => 'wpostOptionLink' - when 2 - link = link_to '关闭匿评', Setting.protocol + "://" + Setting.host_name + "/homework_common/" + homework.id.to_s + "/alert_anonymous_comment?hw_status=" + hw_status.to_s + "&user_activity_id=" + user_activity_id.to_s, id: "#{homework.id}_stop_anonymous_comment", remote: true,:class => 'wpostOptionLink' - when 3 - # link = link_to "匿评结束","javascript:void(0)", :class => "postOptionLink", :title => "匿评结束" - end - else - link = link_to "启动匿评","javascript:void(0)", :class => "wpostOptionLink", :title => "学生提交作业数大于等于2时才可以启动匿评" - end - link - end - #学生根据传入作业确定显示为编辑作品还是新建作品 - def student_new_homework homework - work = cur_user_works_for_homework homework - if work.nil? - link_to "提交作品", new_student_work_path(:homework => homework.id),:class => 'fr mr10 work_edit' - else - if homework.homework_type == 1 && homework.homework_detail_manual && homework.homework_detail_manual.comment_status != 1 #匿评作业,且作业状态不是在开启匿评之前 - link_to "作品已交", "javascript:void(0);", :class => 'fr mr10 pr_join_span c_white', :title => "开启匿评后不可修改作品" - elsif homework.homework_type == 2 #编程作业修改作品 - if homework.homework_detail_manual && homework.homework_detail_manual.comment_status != 1 - link_to "作品已交", "javascript:void(0);", :class => 'fr mr10 pr_join_span c_white', :title => "开启匿评后不可修改作品" - else - link_to "修改作品", new_student_work_path(:homework => homework.id),:class => 'fr mr10 work_edit' - end - else - link_to "修改作品", edit_student_work_path(work.id),:class => 'fr mr10 work_edit' - end - end - end - #动态列表中,确定学生是该提交还是进列表 - def student_work_activity_submit_status(opt={}) - default_opt = {class: 'c_blue'}.merge(opt) - - is_teacher = User.current.user_extensions && User.current.user_extensions.identity == 0 && User.current.allowed_to?(:add_course, nil, :global => true) - - homework = default_opt[:homework] - work = cur_user_works_for_homework homework - if work.nil? && !is_teacher - link_to "提交("+homework.student_works.count.to_s+")", new_student_work_path(:homework => homework.id,:host=> Setting.host_course), :class=> default_opt[:class] - else - link_to "提交("+homework.student_works.count.to_s+")", student_work_index_path(:homework => homework.id,:host=> Setting.host_course), :class=> default_opt[:class] - end - end - - # 试卷动态的按钮 - def user_for_exercise exercise,is_teacher - count = exercise.exercise_users.where(:commit_status => 1, :user_id => exercise.course.student.map(&:student_id)).count - if User.current.logged? - if User.current.member_of_course?(exercise.course) - if is_teacher #老师显示作品数量 - link_to "作品 (#{count})".html_safe, student_exercise_list_exercise_path(exercise), :class => "c_blue homepagePostSubmit" - else #学生显示提交作品、修改作品等按钮 - work = exercise.exercise_users.where("user_id = ?",User.current).first - member = exercise.course.members.where(:user_id => User.current.id).first - setting_time = exercise_group_setting exercise, member.try(:course_group) - if work - if work.commit_status > 0 - link_to "查看答题(#{count})", exercise.exercise_status < 3 ? exercise_path(exercise,:user_id => User.current.id) : show_student_result_exercise_path(exercise,:user_id => User.current.id), :class => "c_blue homepagePostSubmit" - else - if setting_time.publish_time < Time.now && setting_time.end_time > Time.now - link_to (work.start_at.nil? ? "开始答题(#{count})" : "继续答题(#{count})"), exercise_path(exercise,:user_id => User.current.id), :class => "c_blue homepagePostSubmit" - else - link_to "查看作品(#{count})".html_safe, student_exercise_list_exercise_path(exercise), :class => "c_blue homepagePostSubmit" - end - end - else - if setting_time.publish_time < Time.now && setting_time.end_time > Time.now - link_to "开始答题(#{count})", exercise_path(exercise,:user_id => User.current.id), :class => "c_blue homepagePostSubmit" - else - link_to "查看作品(#{count})".html_safe, student_exercise_list_exercise_path(exercise), :class => "c_blue homepagePostSubmit" - end - end - end - else - link_to "作品 (#{count})".html_safe, "javascript:void(0)", :class => "c_blue homepagePostSubmit", :onclick => "notice_sure_box('您不是班级成员,不能答题
    请先从老师处获取邀请码后加入班级,再答题')" - end - else - link_to "作品 (#{count})".html_safe, "javascript:void(0)", :class => "c_blue homepagePostSubmit", :onclick => "login_notice_box('#{signin_url_without_domain}');" - end - end - - # 问卷动态的按钮 - def user_for_poll poll,is_teacher - count = poll.poll_users.where(:commit_status => 1, :user_id => poll.course.student.map(&:student_id)).count - if User.current.logged? - if User.current.member_of_course?(poll.course) - if is_teacher #老师显示作品数量 - link_to "作品 (#{count})".html_safe, student_poll_list_poll_path(poll), :class => "c_blue homepagePostSubmit" - else #学生显示提交作品、修改作品等按钮 - work = poll.poll_users.where("user_id = ?",User.current).first - member = poll.course.members.where(:user_id => User.current.id).first - setting_time = poll_group_setting poll, member.try(:course_group) - if work - if work.commit_status > 0 - link_to "查看答题(#{count})", poll_path(poll,:user_id => User.current.id), :class => "c_blue homepagePostSubmit" - elsif setting_time.publish_time < Time.now && setting_time.end_time > Time.now - link_to (work.start_at.nil? ? "开始答题(#{count})" : "继续答题(#{count})"), poll_path(poll,:user_id => User.current.id), :class => "c_blue homepagePostSubmit" - else - link_to "查看作品(#{count})".html_safe, student_poll_list_poll_path(poll), :class => "c_blue homepagePostSubmit" - end - else - if setting_time.publish_time < Time.now && setting_time.end_time > Time.now - link_to "开始答题(#{count})", poll_path(poll,:user_id => User.current.id), :class => "c_blue homepagePostSubmit" - else - link_to "查看作品(#{count})".html_safe, student_poll_list_poll_path(poll), :class => "c_blue homepagePostSubmit" - end - end - end - else - link_to "作品 (#{count})".html_safe, "javascript:void(0)", :class => "c_blue homepagePostSubmit", :onclick => "notice_sure_box('您不是班级成员,不能答题
    请先从老师处获取邀请码后加入班级,再答题')" - end - else - link_to "作品 (#{count})".html_safe, "javascript:void(0)", :class => "c_blue homepagePostSubmit", :onclick => "login_notice_box('#{signin_url_without_domain}');" - end - end - - #根据传入作业确定显示为编辑作品还是新建作品,或者显示作品数量 - def user_for_homework_common homework,work - if User.current.logged? - project = cur_user_projects_for_homework homework if homework.homework_type == 3 - member = homework.course.members.where(:user_id => User.current.id).first - setting_time = homework_group_setting homework, member.try(:course_group_id) - if homework.homework_type == 4 - if work.nil? - link_to "开始实战", shixun_path(homework.homework_commons_shixuns.shixun), :class => 'edu-default-btn user_bluebg_btn fr mr20 pl7 pr7',:target => "_blank" - else - myshixun = Myshixun.where(:id => work.myshixun_id).first - # is_modify = ShixunModify.where(:myshixun_id => myshixun.try(:id), :shixun_id => myshixun.shixun.try(:id), :status => 1).first - link_to "继续实战", shixun_path(myshixun.shixun), :class => "edu-default-btn user_orangebg_btn fr mr20 pl7 pr7", :target => "_blank" - # if myshixun && is_modify.blank? - # link_to "继续实战", myshixun_game_path(myshixun.current_task, :myshixun_id => myshixun), :class => "edu-default-btn user_orangebg_btn fr mr20 pl7 pr7", :target => "_blank" - # elsif myshixun - # link_to "继续实战", 'javascript:void(0);', :onclick => "sure_box_redirect('#{myshixun_reset_myshixun_path(myshixun)}', '实训已经更新啦,系统正在为您重置');", :class => "edu-default-btn user_orangebg_btn fr mr20 pl7 pr7" - # end - end - elsif work.nil? && setting_time.end_time >= Time.now - if homework.homework_type ==3 && project.nil? && homework.homework_detail_group.base_on_project == 1 - link_to "提交作品", "javascript:void(0)", :class => 'edu-default-btn user_bluebg_btn fr mr20 pl7 pr7',:style=>"cursor:not-allowed",:title => '请先关联项目再提交作品' - else - link_to "提交作品", new_student_work_url_without_domain(homework.id),:class => 'edu-default-btn user_bluebg_btn fr mr20 pl7 pr7' - end - elsif work.nil? && setting_time.end_time < Time.now - if homework.allow_late && !homework.course.is_end - if homework.homework_type ==3 && project.nil? && homework.homework_detail_group.base_on_project == 1 - link_to "补交作品", "javascript:void(0)", :class => 'edu-default-btn user_orangebg_btn fr mr20 pl7 pr7',:style=>"cursor:not-allowed",:title => '请先关联项目再补交作品' - else - link_to "补交作品", new_student_work_url_without_domain(homework.id),:class => 'edu-default-btn user_orangebg_btn fr mr20 pl7 pr7' - end - end - elsif work - work_ids = "(" + homework.student_works.has_committed.map(&:id).join(",") + ")" - if homework.homework_detail_manual && homework.homework_detail_manual.comment_status == 3 && User.current.student_works_evaluation_distributions.where("student_work_id IN #{work_ids}").count > 0 #匿评作业,且作业状态不是在开启匿评之前 - link_to "作品匿评", student_work_index_path(:homework => homework.id), :class => 'edu-default-btn user_orangebg_btn fr mr20 pl7 pr7', :title => "开启匿评后不可修改作品" - elsif homework.homework_detail_manual && homework.homework_detail_manual.comment_status > 3 - link_to "查看作品",student_work_path(work), :class => 'edu-default-btn user_greybg_btn fr mr20 pl7 pr7', :title => "匿评已结束" - elsif setting_time.end_time >= Time.now && work.user_id == User.current.id - link_to "修改作品", edit_student_work_url_without_domain(work.id),:class => 'edu-default-btn user_orangebg_btn fr mr20 pl7 pr7' - else - link_to "查看作品", student_work_path(work), :class => 'edu-default-btn user_greybg_btn fr mr20 pl7 pr7', :title => "作业截止后不可修改作品" - end - end - else - link_to "作品".html_safe, "javascript:void(0)", :class => "edu-default-btn user_greybg_btn fr mr20 pl7 pr7", :onclick => "login_notice_box('#{signin_url_without_domain}');" - end - end - - #根据传入作业确定显示为编辑作品还是新建作品,或者显示作品数量 - def user_for_contest_work homework,is_contestant,work - count = homework.contestant_works.has_committed.count - if User.current.logged? - if User.current.member_of_contest?(homework.contest) || User.current.admin? - if !is_contestant #老师显示作品数量 - link_to "作品(#{count})", contestant_works_path(:work =>homework.id, :tab => 2), :class => "c_blue" - else #学生显示提交作品、修改作品等按钮 - work = cur_user_works_for_work homework - project = cur_user_projects_for_work homework - if work.nil? && homework.work_status == 1 - if homework.work_type ==3 && project.nil? && homework.work_detail_group.base_on_project - link_to "提交作品(#{count})","javascript:void(0)", :class => 'c_grey',:style=>"cursor:not-allowed",:title => '请先关联项目再提交作品' - else - link_to "提交作品(#{count})", new_contestant_work_path(:work => homework.id),:class => 'c_blue' - end - elsif work.nil? && homework.work_status > 1 - if homework.work_type ==3 && project.nil? && homework.work_detail_group.base_on_project - link_to "补交作品(#{count})","javascript:void(0)", :class => 'c_grey',:style=>"cursor:not-allowed",:title => '请先关联项目再补交作品' - else - link_to "补交作品(#{count})", new_contestant_work_path(:work => homework.id),:class => 'c_blue' - end - else - if homework.work_status == 1 && work.user_id == User.current.id - link_to "修改作品(#{count})", edit_contestant_work_path(work.id),:class => 'c_blue' - else - link_to "查看作品(#{count})", contestant_works_path(:work =>homework.id, :tab => 2), :class => 'c_blue', :title => "不可修改作品" - end - end - end - else - link_to "作品(#{count})", "javascript:void(0)", :class => "c_blue", :onclick => "notice_sure_box('您不是参赛者,不能提交作品
    请加入竞赛,待审批通过后再提交作品')" - end - else - link_to "作品(#{count})", "javascript:void(0)", :class => "c_blue", :onclick => "login_notice_box('#{signin_url_without_domain}');" - end - end - - #根据传入作业确定显示为提交作品、补交作品、查看作品等 - def student_for_homework_common homework - if User.current.allowed_to?(:as_teacher, homework.course) - link_to "查看作品", student_work_index_url_in_org(homework.id, 2), :class => 'hw_btn_green fr mt5', :title => "查看作品", :target => '_blank' - else User.current.member_of_course?(homework.course) - work = cur_user_works_for_homework homework - project = cur_user_projects_for_homework homework - if work.nil? && homework.end_time >= Time.now - if homework.homework_type ==3 && project.nil? && homework.homework_detail_group.base_on_project == 1 - link_to "关联项目", student_work_index_url_in_org(homework.id, 1), :class => 'hw_btn_green fr mt5',:title => '查看分组作业详情', :target => '_blank' - else - link_to "提交作品", new_student_work_url_without_domain(homework.id),:class => 'hw_btn_green fr mt5', :target => '_blank' - end - elsif work.nil? && homework.end_time < Time.now - if homework.homework_type ==3 && project.nil? && homework.homework_detail_group.base_on_project == 1 - link_to "关联项目", student_work_index_url_in_org(homework.id, 1), :class => 'hw_btn_green fr mt5',:title => '查看分组作业详情', :target => '_blank' - else - link_to "补交作品", new_student_work_url_without_domain(homework.id),:class => 'btn_orange_big fr mt5', :target => '_blank' - end - else - if homework.homework_detail_manual && homework.homework_detail_manual.comment_status == 2 #匿评作业,且作业状态不是在开启匿评之前 - link_to "作品匿评", student_work_index_url_in_org(homework.id, 2), :class => 'hw_btn_green fr mt5', :title => "开启匿评后不可修改作品", :target => '_blank' - elsif homework.homework_detail_manual && homework.homework_detail_manual.comment_status == 3 - link_to "查看作品",student_work_index_url_in_org(homework.id, 2), :class => 'hw_btn_green fr mt5', :title => "匿评已结束", :target => '_blank' - elsif homework.homework_type == 2 && homework.end_time >= Time.now#编程作业不能修改作品 - link_to "修改作品", new_student_work_url_without_domain(homework.id),:class => 'hw_btn_green fr mt5', :target => '_blank' - elsif homework.end_time >= Time.now && work.user_id == User.current.id - link_to "修改作品", edit_student_work_url_without_domain(work.id),:class => 'hw_btn_green fr mt5', :target => '_blank' - else - link_to "查看作品", student_work_index_url_in_org(homework.id, 2), :class => 'hw_btn_green fr mt5', :title => "作业截止后不可修改作品", :target => '_blank' - end - end - end - end - - def relate_project homework,is_teacher,is_in_course,user_activity_id,course_activity - if User.current.member_of_course?(homework.course) - if is_teacher - #link_to "已关联(#{homework.student_work_projects.count})",student_work_index_path(:homework => homework.id),:class => "c_blue" - else - projects = cur_user_projects_for_homework homework - works = cur_user_works_for_homework homework - if works.nil? && projects.nil? - link_to "关联项目",new_student_work_project_student_work_index_path(:homework => homework.id,:is_in_course=>is_in_course,:user_activity_id=>user_activity_id,:course_activity=>course_activity),remote: true,:class=> 'c_blue', :title=> '请选择分组作业关联的项目' - elsif works.nil? - link_to "取消关联",cancel_relate_project_student_work_index_path(:homework => homework.id,:is_in_course=>is_in_course,:user_activity_id=>user_activity_id,:course_activity=>course_activity), :confirm => "您确定要取消关联吗?", remote: true,:class => "c_blue", :title=> '取消关联项目' - else - #link_to "已关联(#{homework.student_work_projects.count})",student_work_index_path(:homework => homework.id),:class => "c_blue" - end - end - end - end - - def student_anonymous_comment homework - if homework.homework_detail_manual - case homework.homework_detail_manual.comment_status - when 1 - "未开启匿评".html_safe - when 2 - "正在匿评中".html_safe - when 3 - "匿评已结束".html_safe - end - end - end - - #获取当前用户在指定作业下提交的作业的集合 - def cur_user_works_for_homework homework - work = homework.student_works.where("user_id = ? && work_status != 0",User.current).first - # if homework.homework_type == 3 - # pro = homework.student_work_projects.where("user_id = #{User.current.id}").first - # if pro.nil? || pro.student_work_id == "" || pro.student_work_id.nil? - # work = nil - # else - # work = StudentWork.find pro.student_work_id - # end - # end - work - end - #获取当前用户在指定作业下关联的项目的集合 - def cur_user_projects_for_homework homework - homework.student_works.where("user_id = ? and project_id != 0",User.current).first - end - - #获取当前用户在指定题目下提交的作业的集合 - def cur_user_works_for_work homework - work = homework.contestant_works.where("user_id = ? && work_status != 0",User.current).first - if homework.work_type == 3 - pro = homework.contestant_work_projects.where("user_id = #{User.current.id}").first - if pro.nil? || pro.contestant_work_id == "" || pro.contestant_work_id.nil? - work = nil - else - work = ContestantWork.find pro.contestant_work_id - end - end - work - end - #获取当前用户在指定题目下关联的项目的集合 - def cur_user_projects_for_work work - work.contestant_work_projects.where("user_id = ?",User.current).first - end - - #获取当前作业的提交截止时间/互评截止时间 - def cur_homework_end_time homework - str = "" - if homework.anonymous_comment == 0 && homework.end_time && homework.end_time < Time.now && homework.homework_detail_manual - str = "互评截止:#{format_date homework.homework_detail_manual.evaluation_end}" - else - str = "提交截止:#{homework.end_time ? (format_date homework.end_time) : '       --       '}" - end - str - end - - def file_preview_tag(file, html_options={}) - if %w(pdf pptx doc docx xls xlsx).any?{|x| file.filename.downcase.end_with?(x)} - link_to '预览', download_named_attachment_path(file.id, file.filename, preview: true),html_options - end - end - - def file_preview_eye(file, html_options={}) - if %w(pdf pptx doc docx xls xlsx).any?{|x| file.filename.downcase.end_with?(x)} - link_to '', User.current.logged? ? download_named_attachment_path(file.id, file.filename, preview: true) : signin_url_without_domain, html_options - end - end - - #将文本内的/n转换为
    - def text_format text - text.gsub("&","&").gsub("<","<").gsub(">",">").gsub("\n","
    ").html_safe - end - - #评分规则显示 - def scoring_rules late_penalty,homework_id,is_teacher,absence_penalty=nil - if absence_penalty - if late_penalty.to_i == 0 && absence_penalty.to_i == 0 - notice = "尚未设置评分规则" - if is_teacher - notice += ",请 " + link_to("设置",edit_homework_common_path(homework_id),:class => "c_green") - end - elsif late_penalty.to_i != 0 && absence_penalty.to_i == 0 - notice = "迟交扣#{late_penalty}分,缺评扣分未设置" - elsif late_penalty.to_i == 0 && absence_penalty.to_i != 0 - notice = "迟交扣分未设置,缺评一个作品扣#{absence_penalty}分" - elsif late_penalty.to_i != 0 && absence_penalty.to_i != 0 - notice = "迟交扣#{late_penalty}分,缺评一个作品扣#{absence_penalty}分" - end - else - if late_penalty.to_i == 0 - notice = "尚未设置评分规则" - if is_teacher - notice += ",请 " + link_to("设置",edit_homework_common_path(homework_id),:class => "c_green") - end - else - notice = "迟交扣#{late_penalty}分" - end - end - notice.html_safe - end - - #老师C语言的标准代码 - def c_stantard_code_teacher - "// 老师您好!这是一个C语言的样例程序 -// 程序功能:输入两个整数,输出两者之和 -// 测试集合:老师可以给出多组测试集,例如: -// 输入1和2,输出3 -// 输入3和4,输出7 -// ... ... -// 系统将根据您给出的测试集对学生代码进行自动评分 - -// 特别提醒:程序采用命令行传参方式,输入通过argv传入 -// 否则您的作业标准代码将不能通过测试 - -#include //引用必须头文件 -int main(int argc, char** argv) { - int a = atoi(argv[1]); //将第一个输入转成整型 - int b = atoi(argv[2]); //将第二个输入转换为整型 - - printf(\"%d\",a+b); //输出a+b - return 0; -}".html_safe - end - - #老师C++语言的标准代码 - def c_stantard_code_teacher_ - "// 老师您好!这是一个C++语言的样例程序 -// 程序功能:输入两个整数,输出两者之和 -// 测试集合:老师可以给出多组测试集,例如: -// 输入1和2,输出3 -// 输入3和4,输出7 -// ... ... -// 系统将根据您给出的测试集对学生代码进行自动评分 - -// 特别提醒:程序采用命令行传参方式,输入通过argv传入 -// 否则您的作业标准代码将不能通过测试 - -#include //引用必须头文件 -#include -using namespace std; -int main(int argc, char** argv){ - int a = atoi(argv[1]); //将第一个输入转成整型 - int b = atoi(argv[2]); //将第二个输入转换为整型 - cout< //引用必须头文件 -int main(int argc, char** argv) { - int a = atoi(argv[1]); //将第一个输入转成整型 - int b = atoi(argv[2]); //将第二个输入转换为整型 - - printf(\"%d\",a+b); //输出a+b - return 0; -}".html_safe - end - - #学生C++语言的标准代码 - def c_stantard_code_student_ - "// 同学好!这是一个C++语言的样例程序 -// 程序功能:输入两个整数,输出两者之和 -// 测试集合:老师可以给出多组测试集,例如: -// 输入1和2,输出3 -// 输入3和4,输出7 -// ... ... -// 系统将根据您给出的测试集对学生代码进行自动评分 - -// 特别提醒:程序采用命令行传参方式,输入通过argv传入 -// 否则您的作业标准代码将不能通过测试 - -#include //引用必须头文件 -#include -using namespace std; -int main(int argc, char** argv){ - int a = atoi(argv[1]); //将第一个输入转成整型 - int b = atoi(argv[2]); //将第二个输入转换为整型 - cout<&1 | base64) - if [ -z \"$compileResult\" ]; then - compileResult=$(echo -n \"compile successfully\" | base64) - fi - -} -compile $1" - end - - def execute_command - "execute(){ - #执行命令 - executeCommand=\"EXECUTECOMMAND\" - #执行文件名 - sourceClassName=${sourceClassNames[$1 - 1]} - challengeStage=$1 - - output='' - i=0 - while [[ i -lt ${#ins[*]} ]]; do - #执行,并拼接执行结果 - result=$(echo \"${ins[$i]}\" | base64 -d | $executeCommand $sourceClassName 2>&1 | base64) - #拼接输出结果 - output=$output\\\"$result\\\", - let i++ - done - output=\"[${output%?}]\" -} - -execute $1 -" - end - - def challenge_file_path - "#用户打开的文件名,之所以传过来这个,是因为可以从这个里面提取出来执行文件名 -challengeProgramNames=(CHALLENGEPROGRAMNAMES)" - end - - - def import_ke(default_opt={}) - opt = {enable_at: false, prettify: false, init_activity: false}.merge default_opt - ss = '' - - unless Setting.at_enabled? - opt[:enable_at] = false - end - - ss += javascript_include_tag("/assets/kindeditor/kindeditor",'/assets/kindeditor/pasteimg') - if opt[:enable_at] - ss += javascript_include_tag('/assets/kindeditor/at/jquery.caret.min.js', '/assets/kindeditor/at/jquery.atwho.js', '/assets/kindeditor/at/config.js') - ss += stylesheet_link_tag("/assets/kindeditor/at/jquery.atwho.css") - end - - if opt[:prettify] - ss += javascript_include_tag 'prettify' - ss += stylesheet_link_tag 'prettify' - end - - if opt[:init_activity] - ss += javascript_include_tag "create_kindeditor" - end - - ss.html_safe - end - - #竞赛动态的更新 - def update_contest_activity type, id - contest_activity = ContestActivity.where("contest_act_type=? and contest_act_id =?", type.to_s, id).first - if contest_activity - contest_activity.updated_at = Time.now - contest_activity.save - end - end - #课程动态的更新 - def update_course_activity type, id - course_activity = CourseActivity.where("course_act_type=? and course_act_id =?", type.to_s, id).first - if course_activity - course_activity.updated_at = Time.now - course_activity.save - end - end - #首页动态更新 - def update_user_activity type, id -=begin - user_activity = UserActivity.where("act_type=? and act_id =?", type.to_s, id).first - if user_activity - user_activity.updated_at = Time.now - user_activity.save - end -=end - end - #项目动态更新 - def update_forge_activity type, id - forge_activity = ForgeActivity.where("forge_act_type=? and forge_act_id=?", type.to_s, id).first - if forge_activity - forge_activity.updated_at = Time.now - forge_activity.save - end - end - #组织动态更新 - def update_org_activity type , id -=begin - org_activity = OrgActivity.where("org_act_type=? and org_act_id =?", type.to_s, id).first - if org_activity - org_activity.updated_at = Time.now - org_activity.save - end -=end - end - #个人动态更新 - def update_principal_activity type, id -=begin - principal_activity = PrincipalActivity.where("principal_act_type=? and principal_act_id =?", type.to_s, id).first - if principal_activity - principal_activity.updated_at = Time.now - principal_activity.save - end -=end - end - - #项目按更新时间排序 - def project_sort_update projects - unless projects.empty? - project_ids = '('+projects.map{|pro|pro.project_id}.join(',')+')' - sort_projects = ForgeActivity.find_by_sql("SELECT MAX(updated_at) AS updated_at,user_id, project_id FROM forge_activities WHERE project_id IN #{project_ids} GROUP BY project_id ORDER BY MAX(updated_at) DESC") - #sort_projects = sort_projects.sort_by{|sp| (!sp.project.project_score.nil? && !sp.project.project_score.commit_time.nil?) ? '' : sp.project.project_score.commit_time} - return sort_projects - end - end - - def project_sort_first projects - unless projects.empty? - project_ids = '('+projects.map{|pro|pro.project_id}.join(',')+')' - sort_projects = ForgeActivity.find_by_sql("SELECT updated_at,user_id, project_id FROM forge_activities WHERE project_id IN #{project_ids} ORDER BY updated_at DESC limit 1") - return sort_projects - end - end - - def sort_tag(content, opts) - options = {} - options[:sort_by] = opts.delete(:name) - is_current_sort = params[:sort_by].to_s == options[:sort_by] - options[:sort_direction] = is_current_sort && params[:sort_direction].to_s == 'desc' ? 'asc' : 'desc' - - path = opts.delete(:path) + "?" + params.merge(options).to_query - arrow_class = case params[:sort_direction].to_s - when 'desc' then 'fa-long-arrow-down' - when 'asc' then 'fa-long-arrow-up' - else '' - end - - content_tag(:span, opts) do - link_to path, remote: true do - content += content_tag(:i, '', class: "fa color-light-green ml5 #{arrow_class}") if is_current_sort - raw content - end - end - end -end - -def user_url_in_org(user_id) - Setting.protocol + "://" + Setting.host_name + "/users/" + user_id.to_s -end - -def project_issues_url_in_org(project_id) - Setting.protocol + "://" + Setting.host_name + "/projects/" + project_id.to_s + "/issues" -end - -def issue_url_in_org(id) - Setting.protocol + "://" + Setting.host_name + "/issues/" + id.to_s -end - -def project_boards_url_in_org(id) - Setting.protocol + "://" + Setting.host_name + "/projects/" + id.to_s + "/boards" -end - -def board_message_url_in_org(board_id, message_id) - Setting.protocol + "://" + Setting.host_name + "/boards/" + board_id.to_s + "/topics/" + message_id.to_s -end - -def project_url_in_org(id) - Setting.protocol + "://" + Setting.host_name + "/projects/" + id.to_s -end - -def homework_common_index_url_in_org(course_id) - Setting.protocol + "://" + Setting.host_name + "/homework_common?course=" + course_id.to_s -end - -def student_work_index_url_in_org(homework_id, tab = 1, is_focus = '', show_work_id = '') - if is_focus != '' - Setting.protocol + "://" + Setting.host_name + "/student_work?homework=" + homework_id.to_s + "&tab=" + tab.to_s + "&is_focus=" + is_focus.to_s - elsif show_work_id != '' - Setting.protocol + "://" + Setting.host_name + "/student_work?homework=" + homework_id.to_s + "&tab=" + tab.to_s + "&show_work_id=" + show_work_id.to_s - else - Setting.protocol + "://" + Setting.host_name + "/student_work?homework=" + homework_id.to_s + "&tab=" + tab.to_s - end -end - - -def contestant_work_index_url_in_org(work_id, tab = 1, is_focus = '', show_work_id = '') - if is_focus != '' - Setting.protocol + "://" + Setting.host_name + "/contestant_work?work=" + work_id.to_s + "&tab=" + tab.to_s + "&is_focus=" + is_focus.to_s - elsif show_work_id != '' - Setting.protocol + "://" + Setting.host_name + "/contestant_work?work=" + work_id.to_s + "&tab=" + tab.to_s + "&show_work_id=" + show_work_id.to_s - else - Setting.protocol + "://" + Setting.host_name + "/contestant_work?work=" + work_id.to_s + "&tab=" + tab.to_s - end -end - -def course_url_in_org(course_id) - Setting.protocol + "://" + Setting.host_name + "/courses/" + course_id.to_s -end - -def user_watchlist_url_in_org(id) - Setting.protocol + "://" + Setting.host_name + "/users/" + id.to_s + "/user_watchlist" -end - -def user_fanslist_url_in_org(id) - Setting.protocol + "://" + Setting.host_name + "/users/" + id.to_s + "/user_fanslist" -end - -def user_blogs_url_in_org(user_id) - Setting.protocol + "://" + Setting.host_name + "/users/" + user_id.to_s + "/blogs" -end - -def feedback_url_in_org(user_id) - Setting.protocol + "://" + Setting.host_name + "/users/" + user_id.to_s + "/user_newfeedback" -end - -def user_activities_url_in_org(user_id) - Setting.protocol + "://" + Setting.host_name + "/users/" + user_id.to_s + "/user_activities" -end - -def course_news_index_url_in_org(course_id) - Setting.protocol + "://" + Setting.host_name + "/courses/" + course_id.to_s + "/news" -end - -def news_url_in_org(news_id) - Setting.protocol + "://" + Setting.host_name + "/news/" + news_id.to_s -end - -def course_boards_url_in_org(course_id) - Setting.protocol + "://" + Setting.host_name + "/courses/" + course_id.to_s + "/boards" -end - -def logout_url_without_domain - Setting.protocol + "://" + Setting.host_name + "/logout" -end - -def signin_url_without_domain - Setting.protocol + "://" + Setting.host_name + "/login?login=true" -end - -def register_url_without_domain - Setting.protocol + "://" + Setting.host_name + "/login?login=false" -end - -def new_student_work_url_without_domain(homework_id) - Setting.protocol + "://" + Setting.host_name + "/student_work/new?homework=" + homework_id.to_s -end - -def edit_student_work_url_without_domain(homework_id) - Setting.protocol + "://" + Setting.host_name + "/student_work/" + homework_id.to_s + "/edit" -end - -def download_named_attachment_url_without_domain(id, filename, option={}) - attachment_id = (Attachment === id ? id.id : id) - Setting.protocol + "://" + Setting.host_name + "/attachments/download/" + attachment_id.to_s + "/" + filename -end - -def named_attachment_url_without_domain(id, filename, option={}) - attachment_id = (Attachment === id ? id.id : id) - Setting.protocol + "://" + Setting.host_name + "/attachments/" + attachment_id.to_s + "/" + filename -end - -#判断是否为默认的组织栏目 -def is_default_field? field - (field.name == 'activity' || field.name == 'course' || field.name == 'project' ) && field.field_type == 'default' -end - -def host_with_protocol - return Setting.protocol + "://" + Setting.host_name -end - -def secdomain_with_protocol secdomain - return Setting.protocol + "://" + secdomain + ".trustie.net" -end - -#根据回复类型获取回复 -def get_reply_by_type type, reply_id - reply = nil - case type - when 'HomeworkCommon', 'Work', 'GraduationTopic', 'GraduationTask' - reply = JournalsForMessage.find reply_id - when 'JournalsForMessage' - reply = JournalsForMessage.find reply_id - when 'Message' - reply = Message.find reply_id - when 'BlogComment' - reply = BlogComment.find reply_id - when 'OrgDocumentComment' - reply = OrgDocumentComment.find reply_id - when 'News','Comment' - reply = Comment.find reply_id - when 'Issue', 'TrainingTask' - reply = Journal.find reply_id - when 'Journal' - reply = Journal.find reply_id - when 'Syllabus' - reply = JournalsForMessage.find reply_id - when 'Memo' - reply = Memo.find reply_id - when 'Challenge' - reply = Discuss.find reply_id - end - reply -end - -#获取不包含子节点的回复(前三个) -def get_no_children_comments comments - result = {} - no_children_comments = [] - count = 0 - three_more = false - comments.each do |comment| - if comment.children.blank? - count = count + 1 - if count > 3 - three_more = true - end - break if count > 3 - no_children_comments << comment - end - end - result[:three_more] = three_more - result[:no_children_comments] = no_children_comments - result -end - -#获取不包含子节点的回复(所有) -def get_no_children_comments_all comments - no_children_comments = [] - comments.each do |comment| - if comment.children.blank? - no_children_comments << comment - end - end - no_children_comments -end - -#获取回复的所有父节点 -def get_reply_parents parents_rely, comment - unless comment.parent.nil? - parents_rely << comment.parent - get_reply_parents parents_rely, comment.parent - end - parents_rely -end - -#获取回复的所有父节点(不包括根节点) -def get_reply_parents_no_root parents_rely, comment - if !comment.parent.nil? && !comment.parent.parent.nil? - parents_rely << comment.parent - get_reply_parents_no_root parents_rely, comment.parent - end - parents_rely -end - -def get_all_children_ex result, jour - if jour.kind_of? Message - jour.children.includes(:author, :praise_tread_cache).each do |jour_child| - result << jour_child - get_all_children_ex result, jour_child - end - elsif (jour.kind_of? JournalsForMessage) || (jour.kind_of? BlogComment) || (jour.kind_of? OrgDocumentComment) - jour.children.each do |jour_child| - result << jour_child - get_all_children_ex result, jour_child - end - end - result -end - -#获取所有子节点 -def get_all_children result, jour - if jour.kind_of? Message - jour.children.includes(:author, :praise_tread_cache).each do |jour_child| - result << jour_child - get_all_children_ex result, jour_child - end - elsif (jour.kind_of? JournalsForMessage) || (jour.kind_of? BlogComment) || (jour.kind_of? OrgDocumentComment) - jour.children.each do |jour_child| - result << jour_child - get_all_children_ex result, jour_child - end - end - if jour.respond_to?(:created_on) - result.sort! { |a,b| b.created_on <=> a.created_on } - elsif jour.respond_to?(:created_at) - result.sort! { |a,b| b.created_at <=> a.created_at } - end - result -end - -#获取该节点所在的帖子 -def get_root_parent comment - while comment.parent - comment = comment.parent - end - comment -end - - - -#将有置顶属性的提到数组前面 -def sort_by_sticky topics - tmpTopics = [] - tmpIndex = 0 - topics.each do |topic| - if topic.sticky == 1 - tmpTopics[tmpIndex] = topic - tmpIndex = tmpIndex + 1 - end - end - - topics.each do |topic| - if topic.sticky == 0 - tmpTopics[tmpIndex] = topic - tmpIndex = tmpIndex + 1 - end - end - return tmpTopics -end - -#按人气排序的时候 相同的人气必须按某种时间顺序排序 有置顶属性 -def sortby_time_countcommon_hassticky topics,sortstr - tmpTopics = [] - tmpTopics = topics - tStart = -1 - tEnd = -1 - - tmpTopics_1 = [] - tmpIndex = 0 - - tmpTopics.each_with_index do |topic,index| - if topic.sticky == 0 - if tStart == -1 - if (index != tmpTopics.count-1) && (topic[:infocount] == tmpTopics[index+1][:infocount]) - tStart = index - end - else - if ((topic[:infocount] == tmpTopics[index-1][:infocount]) && ((index != tmpTopics.count-1) && (topic[:infocount] == tmpTopics[index+1][:infocount]))) - tEnd = index - else - if (topic[:infocount] == tmpTopics[index-1][:infocount]) - tEnd = index - end - if tEnd > tStart - for i in tStart..tEnd - tmpTopics_1[tmpIndex] = tmpTopics[i] - tmpIndex = tmpIndex + 1 - end - - if sortstr == "created_at" - tmpTopics_1 = tmpTopics_1.sort{|x,y| y[:created_at].to_i <=> x[:created_at].to_i } - elsif sortstr == "created_on" - tmpTopics_1 = tmpTopics_1.sort{|x,y| y[:created_on].to_i <=> x[:created_on].to_i } - elsif sortstr == "updated_at" - tmpTopics_1 = tmpTopics_1.sort{|x,y| y[:updated_at].to_i <=> x[:updated_at].to_i } - elsif sortstr == "updated_on" - tmpTopics_1 = tmpTopics_1.sort{|x,y| y[:updated_on].to_i <=> x[:updated_on].to_i } - end - - tmpIndex = 0 - for i in tStart..tEnd - tmpTopics[i] = tmpTopics_1[tmpIndex] - tmpIndex = tmpIndex + 1 - end - end - tStart = -1 - tEnd = -1 - tmpTopics_1 = [] - tmpIndex = 0 - end - end - end - end - return tmpTopics -end - -#按人气排序的时候 相同的人气必须按某种时间顺序排序 无置顶属性 -def sortby_time_countcommon_nosticky topics,sortstr - tmpTopics = [] - tmpTopics = topics - tStart = -1 - tEnd = -1 - - tmpTopics_1 = [] - tmpIndex = 0 - - tmpTopics.each_with_index do |topic,index| - if tStart == -1 - if (index != tmpTopics.count-1) && (topic[:infocount] == tmpTopics[index+1][:infocount]) - tStart = index - end - else - if ((topic[:infocount] == tmpTopics[index-1][:infocount]) && ((index != tmpTopics.count-1) && (topic[:infocount] == tmpTopics[index+1][:infocount]))) - tEnd = index - else - if (topic[:infocount] == tmpTopics[index-1][:infocount]) - tEnd = index - end - if tEnd > tStart - for i in tStart..tEnd - tmpTopics_1[tmpIndex] = tmpTopics[i] - tmpIndex = tmpIndex + 1 - end - - if sortstr == "created_at" - tmpTopics_1 = tmpTopics_1.sort{|x,y| y[:created_at].to_i <=> x[:created_at].to_i } - elsif sortstr == "created_on" - tmpTopics_1 = tmpTopics_1.sort{|x,y| y[:created_on].to_i <=> x[:created_on].to_i } - elsif sortstr == "updated_at" - tmpTopics_1 = tmpTopics_1.sort{|x,y| y[:updated_at].to_i <=> x[:updated_at].to_i } - elsif sortstr == "updated_on" - tmpTopics_1 = tmpTopics_1.sort{|x,y| y[:updated_on].to_i <=> x[:updated_on].to_i } - end - - tmpIndex = 0 - for i in tStart..tEnd - tmpTopics[i] = tmpTopics_1[tmpIndex] - tmpIndex = tmpIndex + 1 - end - end - tStart = -1 - tEnd = -1 - tmpTopics_1 = [] - tmpIndex = 0 - end - end - end - return tmpTopics -end - -def strip_html(text,len=0,endss="...") - ss = "" - if !text.nil? && text.length>0 - ss=text.gsub(/<\/?.*?>/, '').strip - ss = ss.gsub(/ */, ' ') - - if len > 0 && ss.length > len - ss = ss[0, len] + endss - elsif len > 0 && ss.length <= len - ss = ss - #ss = truncate(ss, :length => len) - end - end - return ss -end - -def message_content content - content = (strip_html content).strip - content = content.gsub(/\s+/, " ") - if content.gsub(" ", "") == "" - content = "[非文本消息]" - end - content -end - -def get_work_index(hw,is_teacher) - if is_teacher - works = hw.contest.works.order("created_at asc") - else - works = hw.contest.works.where("publish_time <= '#{Date.today}'").order("created_at asc") - end - hw_ids = works.map{|hw| hw.id} if !works.empty? - index = hw_ids.index(hw.id).to_i - return index -end - -def get_poll_index(poll, course, is_teacher) - if is_teacher - polls = course.polls.order("IF(ISNULL(publish_time),0,1),publish_time DESC, created_at DESC") - elsif User.current.member_of_course?(course) - member = course.members.where(:user_id => User.current.id).first - if member.try(:course_group_id).to_i == 0 - polls = course.polls.where("publish_time <= '#{Time.now}' and unified_setting = 1").order("IF(ISNULL(publish_time),0,1),publish_time DESC, created_at DESC") - else - not_poll_ids = course.poll_group_settings.where("course_group_id = #{member.try(:course_group_id)} and (publish_time > '#{Time.now}' or publish_time is null)") - not_poll_ids = not_poll_ids.blank? ? "(-1)" : "(" + not_poll_ids.map(&:poll_id).join(",") + ")" - polls = course.polls.where("publish_time <= '#{Time.now}' and id not in #{not_poll_ids}").order("IF(ISNULL(publish_time),0,1),publish_time DESC, created_at DESC") - end - else - polls = course.polls.where("publish_time <= '#{Time.now}'").order("IF(ISNULL(publish_time),0,1),publish_time DESC, created_at DESC") - end - poll_ids = polls.map{|poll| poll.id} if !polls.blank? - index = poll_ids.length - 1 - poll_ids.index(poll.id).to_i - return index -end - -def get_ex_index(exercise, course, is_teacher) - if is_teacher - exercises = course.exercises.order("IF(ISNULL(publish_time),0,1),publish_time DESC, created_at DESC") - elsif User.current.member_of_course?(course) - member = course.members.where(:user_id => User.current.id).first - if member.try(:course_group_id).to_i == 0 - exercises = course.exercises.where("publish_time <= '#{Time.now}' and unified_setting = 1").order("IF(ISNULL(publish_time),0,1),publish_time DESC, created_at DESC") - else - not_exercise_ids = course.exercise_group_settings.where("course_group_id = #{member.try(:course_group_id)} and (publish_time > '#{Time.now}' or publish_time is null)") - not_exercise_ids = not_exercise_ids.blank? ? "(-1)" : "(" + not_exercise_ids.map(&:exercise_id).join(",") + ")" - exercises = course.exercises.where("publish_time <= '#{Time.now}' and id not in #{not_exercise_ids}").order("IF(ISNULL(publish_time),0,1),publish_time DESC, created_at DESC") - end - else - exercises = course.exercises.where("publish_time <= '#{Time.now}'").order("IF(ISNULL(publish_time),0,1),publish_time DESC, created_at DESC") - end - ex_ids = exercises.map{|ex| ex.id} if !exercises.blank? - index = ex_ids.length - 1 - ex_ids.index(exercise.id).to_i - return index -end - -def get_task_index task, is_teacher - if is_teacher - tasks = task.course.graduation_tasks.order("IF(ISNULL(publish_time),0,1),publish_time DESC, created_at DESC") - else - tasks = task.course.graduation_tasks.where("publish_time <= '#{Time.now}'").order("IF(ISNULL(publish_time),0,1),publish_time DESC, created_at DESC") - end - task_ids = tasks.pluck(:id) - index = task_ids.length - task_ids.index(task.id).to_i - return index -end - -def get_hw_index(hw,is_teacher,type=0) - homework_commons = hw.course.homework_commons - course = hw.course - category_str = hw.course_homework_category_id.nil? ? "is null" : "= #{hw.course_homework_category_id}" - if is_teacher - if type != 0 - homeworks = homework_commons.where("homework_commons.homework_type = #{type} and course_homework_category_id #{category_str}").order("IF(ISNULL(publish_time),0,1),publish_time DESC, created_at DESC") - else - homeworks = homework_commons.where("course_homework_category_id #{category_str}").order("publish_time desc") - end - elsif User.current.member_of_course?(course) - member = course.members.where(:user_id => User.current.id).first - if member.try(:course_group_id).to_i == 0 - if type != 0 - homeworks = homework_commons.where("course_homework_category_id #{category_str} and homework_commons.homework_type = #{type} and publish_time <= '#{Time.now}' and unified_setting = 1").order("IF(ISNULL(publish_time),0,1),publish_time DESC, created_at DESC") - else - homeworks = homework_commons.where("course_homework_category_id #{category_str} and publish_time <= '#{Time.now}' and unified_setting = 1").order("IF(ISNULL(publish_time),0,1),publish_time DESC, created_at DESC") - end - else - not_homework_ids = course.homework_group_settings.where("course_group_id = #{member.try(:course_group_id)} and (publish_time > '#{Time.now}' or publish_time is null)") - not_homework_ids = not_homework_ids.blank? ? "(-1)" : "(" + not_homework_ids.map(&:homework_common_id).join(",") + ")" - if type != 0 - homeworks = homework_commons.where("course_homework_category_id #{category_str} and homework_commons.homework_type = #{type} and publish_time <= '#{Time.now}' and id not in #{not_homework_ids}").order("IF(ISNULL(publish_time),0,1),publish_time DESC, created_at DESC") - else - homeworks = homework_commons.where("course_homework_category_id #{category_str} and publish_time <= '#{Time.now}' and id not in #{not_homework_ids}").order("IF(ISNULL(publish_time),0,1),publish_time DESC, created_at DESC") - end - end - else - if type != 0 - homeworks = homework_commons.where("course_homework_category_id #{category_str} and homework_commons.homework_type = #{type} and publish_time <= '#{Time.now}'").order("IF(ISNULL(publish_time),0,1),publish_time DESC, created_at DESC") - else - homeworks = homework_commons.where("course_homework_category_id #{category_str} and publish_time <= '#{Time.now}'").order("IF(ISNULL(publish_time),0,1),publish_time DESC, created_at DESC") - end - end - hw_ids = homeworks.map{|hw| hw.id} if !homeworks.blank? - index = hw_ids.blank? ? 1 : (hw_ids.length - 1 - hw_ids.index(hw.id).to_i) - return index -end - -def get_hw_status homework_common - str = "" - if homework_common.homework_detail_manual - if homework_common.homework_detail_manual.comment_status == 0 && homework_common.publish_time.nil? - str += '未发布' - elsif homework_common.homework_detail_manual.comment_status == 0 - str += '未发布' - elsif homework_common.homework_detail_manual.comment_status == 1 - if homework_common.anonymous_comment == 0 - str += '未开启匿评' - else - str += '匿评已禁用' - end - if homework_common.end_time >= Time.now - str += '作品提交中' - elsif homework_common.end_time < Time.now && homework_common.anonymous_comment == 1 && User.current.allowed_to?(:as_teacher, homework_common.course) - str += '教师评阅中' - else - str += '作品补交中' - end - elsif homework_common.homework_detail_manual.comment_status == 2 - if homework_common.anonymous_comment == 0 - str += '匿评中' - else - str += '匿评已禁用' - end - str += '教师评阅中' - elsif homework_common.homework_detail_manual.comment_status == 3 - if homework_common.anonymous_comment == 0 - str += '匿评已结束' - else - str += '匿评已禁用' - end - str += '教师评阅中' - end - end - str -end - -def get_cw_status contest_work - str = "" - if contest_work.work_status == 0 && contest_work.publish_time.nil? - str += '挂起' - elsif contest_work.work_status == 0 - str += '未发布' - elsif contest_work.work_status == 1 - if Time.parse(contest_work.end_time.to_s).strftime("%Y-%m-%d") >= Time.now.strftime("%Y-%m-%d") - str += '作品提交中' - else - str += '作品补交中' - end - elsif contest_work.work_status == 2 - str += '提交已截止' - elsif contest_work.work_status == 3 - str += '在线评审中' - elsif contest_work.work_status == 4 - str += '评审已截止' - end - str -end - - -def get_group_member_names user_ids - result = "" - user_ids.each do |user_id| - user = User.where(:id => user_id).first - unless user.nil? - if result != "" - result += "、#{user.show_name}" - else - result += user.show_name - end - end - end - result -end - -def get_contest_group_member_names work - result = "" - unless work.nil? - work.contestant_work_projects.each do |member| - user = User.where(:id => member.user_id).first - unless user.nil? - if result != "" - result += "、#{user.show_name}" - else - result += user.show_name - end - end - end - end - result -end - -def course_syllabus_option syllabus_id = nil - syllabus_members = SyllabusMember.where("user_id = #{User.current.id}") - syllabus_ids = syllabus_members.map{|mem| mem.syllabus_id} - if syllabus_id && !syllabus_ids.include?(syllabus_id) - syllabus_ids << syllabus_id - end - syllabus_ids = syllabus_ids.empty? ? "(-1)" : "(" + syllabus_ids.join(',') + ")" - syllabuses = Syllabus.where("id in #{syllabus_ids}") - type = [] - option1 = [] - option1 << "请选择课程" - option1 << 0 - type << option1 - unless syllabuses.empty? - syllabuses.each do |syllabus| - option = [] - option << syllabus.title - option << syllabus.id - type << option - end - end - type -end - -def create_polls_tiding poll, members - tid_str = "" - if poll.tidings.where(:parent_container_type => "PollPublish", :user_id => poll.course.teachers.map(&:user_id)).count == 0 - poll.course.teachers.find_each do |member| - tid_str += "," if tid_str != "" - tid_str += "(#{member.user_id}, #{poll.user_id}, #{poll.id}, 'Poll', #{poll.id}, 'PollPublish', #{poll.course.id}, 'Course', 0, 'Poll', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}')" - end - end - - members.find_each do |student| - tid_str += "," if tid_str != "" - tid_str += "(#{student.user_id}, #{poll.user_id}, #{poll.id}, 'Poll', #{poll.id}, 'PollPublish', #{poll.course_id}, 'Course', 0, 'Poll', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}')" - end - - if tid_str != "" - tid_sql = "insert into tidings (user_id, trigger_user_id, container_id, container_type, parent_container_id, parent_container_type, belong_container_id, belong_container_type, viewed, tiding_type, created_at, updated_at) values" + tid_str - ActiveRecord::Base.connection.execute tid_sql - end -end - -def create_polls_list poll - str = "" - poll.course.student.find_each do |student| - str += "," if str != "" - str += "(#{student.user_id},#{poll.id}, 0, '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}')" - end - - if str != "" - sql = "insert into poll_users (user_id, poll_id, commit_status, created_at, updated_at) values" + str - ActiveRecord::Base.connection.execute sql - end -end - -def create_exercises_tiding exercise, members - tid_str = "" - if exercise.tidings.where(:parent_container_type => "ExercisePublish", :user_id => exercise.course.teachers.map(&:user_id)).count == 0 - exercise.course.teachers.find_each do |member| - tid_str += "," if tid_str != "" - tid_str += "(#{member.user_id}, #{exercise.user_id}, #{exercise.id}, 'Exercise', #{exercise.id}, 'ExercisePublish', #{exercise.course.id}, 'Course', 0, 'Exercise', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}')" - end - end - - members.find_each do |student| - tid_str += "," if tid_str != "" - tid_str += "(#{student.user_id}, #{exercise.user_id}, #{exercise.id}, 'Exercise', #{exercise.id}, 'ExercisePublish', #{exercise.course_id}, 'Course', 0, 'Exercise', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}')" - end - - if tid_str != "" - tid_sql = "insert into tidings (user_id, trigger_user_id, container_id, container_type, parent_container_id, parent_container_type, belong_container_id, belong_container_type, viewed, tiding_type, created_at, updated_at) values" + tid_str - ActiveRecord::Base.connection.execute tid_sql - end -end - -def create_exercises_list exercise - str = "" - exercise.course.student.find_each do |student| - str += "," if str != "" - str += "(#{student.user_id}, #{exercise.id}, 0, '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}')" - end - - if str != "" - sql = "insert into exercise_users (user_id, exercise_id, commit_status, created_at, updated_at) values" + str - ActiveRecord::Base.connection.execute sql - end -end - -def create_works_tiding homework, members - tid_str = "" - if homework.tidings.where(:parent_container_type => "HomeworkPublish", :user_id => homework.course.teachers.map(&:user_id)).count == 0 - homework.course.teachers.find_each do |member| - tid_str += "," if tid_str != "" - tid_str += "(#{member.user_id}, #{homework.user_id}, #{homework.id}, 'HomeworkCommon', #{homework.id}, 'HomeworkPublish', #{homework.course.id}, 'Course', 0, 'HomeworkCommon', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}')" - end - end - members.find_each do |student| - tid_str += "," if tid_str != "" - tid_str += "(#{student.user_id}, #{homework.user_id}, #{homework.id}, 'HomeworkCommon', #{homework.id}, 'HomeworkPublish', #{homework.course_id}, 'Course', 0, 'HomeworkCommon', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}')" - end - if tid_str != "" - tid_sql = "insert into tidings (user_id, trigger_user_id, container_id, container_type, parent_container_id, parent_container_type, belong_container_id, belong_container_type, viewed, tiding_type, created_at, updated_at) values" + tid_str - ActiveRecord::Base.connection.execute tid_sql - end -end - -def create_works_list homework - if homework.course.present? && homework.course.student.count > 0 - str = "" - name = homework.name - name_str = name + "的作品提交" - homework.course.student.each do |student| - str += "," if str != "" - str += "('#{name_str}',#{homework.id},#{student.user_id}, '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}')" - end - if str != "" - sql = "insert into student_works (name, homework_common_id, user_id, created_at, updated_at) values" + str - ActiveRecord::Base.connection.execute sql - end - end -end - -def add_to_homework_bank_f homework - homework_bank = HomeworkBank.new(:name => homework.name, :description => homework.description, :user_id => User.current.id, :homework_type => homework.homework_type, - :quotes => 1, :is_public => 0, :applicable_syllabus => homework.course.course_list_name, :homework_common_id => homework.id, - :reference_answer => homework.reference_answer, :course_list_id => homework.course.course_list_id) - if homework.homework_type == 2 && homework.homework_detail_programing - homework_bank.language = homework.homework_detail_programing.language - homework.homework_tests.each_with_index do |homework_test| - homework_bank.homework_bank_tests << HomeworkBankTest.new( - input: homework_test.input, - output: homework_test.output - ) - end - homework.homework_samples.each_with_index do |homework_test| - homework_bank.homework_bank_samples << HomeworkBankSample.new( - input: homework_test.input, - output: homework_test.output - ) - end - elsif homework.homework_type == 3 && homework.homework_detail_group - homework_bank.min_num = homework.homework_detail_group.min_num - homework_bank.max_num = homework.homework_detail_group.max_num - homework_bank.base_on_project = homework.homework_detail_group.base_on_project - end - homework.attachments.each do |attachment| - att = attachment.copy - att.container_id = nil - att.container_type = nil - att.author_id = homework_bank.user_id - att.copy_from = attachment.id - att.save - homework_bank.attachments << att - end - homework_bank -end - -# 获取项目动态更新时间 -def get_forge_act_message(act, type) - forge_act = ForgeActivity.where(:forge_act_id => act.id, :forge_act_type => type).first - format_time(forge_act.nil? ? act.created_on : forge_act.try(:updated_at)) -end - -#作业类型 -def homework_type_option - type = [] - option0 = [] - option0 << "请选择作业类型" - option0 << 0 - option1 = [] - option1 << "普通作业" - option1 << 1 - option2 = [] - option2 << "编程作业" - option2 << 2 - option3 = [] - option3 << "分组作业" - option3 << 3 - type << option0 - type << option1 - type << option2 - type << option3 - type -end - -# 竞赛题目类型 -def work_type_option - type = [] - option0 = [] - option0 << "请选择竞赛类型" - option0 << 0 - option1 = [] - option1 << "普通竞赛" - option1 << 1 - # option2 = [] - # option2 << "编程作业" - # option2 << 2 - option3 = [] - option3 << "团队竞赛" - option3 << 3 - type << option0 - type << option1 - #type << option2 - type << option3 - type -end - -# 当前用户可见的某竞赛下的作品数 -def visable_contest_work contest - if User.current.admin? || User.current.admin_of_contest?(contest) - work_num = contest.works.count - else - work_num = contest.works.where("work_status > 0").count - end - work_num -end - -def searchstudent_by_name users, name - mems = [] - if name != "" - name = name.to_s.downcase - users.each do |m| - username = m.lastname.to_s.downcase + m.firstname.to_s.downcase - if(m.login.to_s.downcase.include?(name) || m.user_extensions[:student_id].to_s.downcase.include?(name) || username.include?(name)) - mems << m - end - end - else - mems = users - end - mems -end - -def contest_feedback_count - @contest.journals_for_messages.where('m_parent_id IS NULL').count -end - -def add_reply_adapter obj, options - #modify by nwb - #添加对课程留言的支持 - #留言回复应该不关系其所属的Class,而关心的是其所属的父留言 - case obj.jour_type - when 'Principal' - obj.jour.add_jour(nil, nil, nil, options) - when 'Project' - Project.add_new_jour(nil, nil, obj.jour_id, options) - when 'Course' - Course.add_new_jour(nil, nil, obj.jour_id, options) - when 'Contest' - Contest.add_new_jour(nil, nil, obj.jour_id, options) - #when 'Bid' - # obj.jour.add_jour(nil, nil, nil, options) - #when 'Contest' - # obj.jour.add_jour(nil, nil, obj.jour_id, options) - #when 'Softapplication' - # obj.jour.add_jour(nil, nil, obj.jour_id, options) - #when 'HomeworkAttach' - # obj.jour.add_jour(nil, nil, obj.jour_id, options) - end - # obj = obj_distinguish_url_origin || User.find_by_id(2) - # if obj.kind_of? User - # obj.add_jour(nil, nil, nil, options) - # elsif obj.kind_of? Project - # Project.add_new_jour(nil, nil, obj.id, options) - # elsif obj.kind_of? Course - # Course.add_new_jour(nil, nil, obj.id, options) - # elsif obj.kind_of? Bid - # obj.add_jour(nil, nil, nil, options) - # elsif obj.kind_of? Contest - # obj.add_jour(nil, nil, obj.id, options) #new added - # elsif obj.kind_of? Softapplication - # obj.add_jour(nil, nil, obj.id, options) #new added - # elsif obj.kind_of? HomeworkAttach - # obj.add_jour(nil, nil, obj.id, options) #new added - # else - # raise "create reply obj unknow type.#{obj.class}" - # end -end - -def sy_resources syllabus - courses = syllabus.courses.not_deleted - attachments = Attachment.where(:container_type => 'Course', :container_id => courses.map(&:id)) - resources = ResourceBank.where(:id => attachments.map(&:resource_bank_id)) - resources -end - -def sy_homeworks syllabus - courses = syllabus.courses.not_deleted - homeworks = HomeworkCommon.where(:course_id => courses.map(&:id)) - homeworks = HomeworkBank.where(:id => homeworks.map(&:homework_bank_id)) - homeworks -end - -# 课堂学生的评测次数 -def course_eval_count course - Output.find_by_sql("select sum(g.evaluate_count) as evaluating_count from games g inner join - (select myshixun_id from student_works sw inner join homework_commons hc on sw.homework_common_id=hc.id and - sw.myshixun_id !=0 and hc.course_id=#{course.id} and homework_type=4) aa on g.myshixun_id=aa.myshixun_id").first.try(:evaluating_count).to_i -end - -# 可以查看到资源库的资源 -def visable_attachemnts_incourse course - return[] unless course - result = [] - course.attachments.each do |attachment| - if attachment.unified_setting - if attachment.is_public? && attachment.is_publish == 1 || User.current == attachment.author || User.current.allowed_to?(:as_teacher,course) || (User.current.member_of_course?(course) && attachment.is_publish == 1) || User.current.admin? - result << attachment - end - else - if attachment.is_public? && attachment.is_publish == 1 && !User.current.member_of_course?(course) || User.current == attachment.author || User.current.allowed_to?(:as_teacher,course) || User.current.admin? - result << attachment - elsif User.current.member_of_course?(course) && attachment.is_publish == 1 - member = course.members.where(:user_id => User.current.id).first - if member.try(:course_group_id).to_i == 0 && attachment.unified_setting - result << attachment - elsif attachment.attachment_group_settings.where("course_group_id = #{member.try(:course_group_id)} and publish_time > '#{Time.now}'").count == 0 - result << attachment - end - end - end - end - result -end - -def visable_course_poll course, is_teacher - if is_teacher - poll_num = course.polls.count - elsif User.current.member_of_course?(course) - member = course.members.where(:user_id => User.current.id).first - if member.try(:course_group_id).to_i == 0 - poll_num = course.polls.where("publish_time <= '#{Time.now}' and unified_setting = 1").count - else - not_poll_ids = course.poll_group_settings.where("course_group_id = #{member.try(:course_group_id)} and (publish_time > '#{Time.now}' or publish_time is null)") - not_poll_ids = not_poll_ids.blank? ? "(-1)" : "(" + not_poll_ids.map(&:poll_id).join(",") + ")" - poll_num = course.polls.where("publish_time <= '#{Time.now}' and id not in #{not_poll_ids}").count - end - else - poll_num = course.polls.where("publish_time <= '#{Time.now}' and unified_setting = 1").count - end - poll_num -end - -def visable_course_exercise course, is_teacher - if is_teacher - exercise_num = course.exercises.count - elsif User.current.member_of_course?(course) - member = course.members.where(:user_id => User.current.id).first - if member.try(:course_group_id).to_i == 0 - exercise_num = course.exercises.where("publish_time <= '#{Time.now}' and unified_setting = 1").count - else - not_exercise_ids = course.exercise_group_settings.where("course_group_id = #{member.try(:course_group_id)} and (publish_time > '#{Time.now}' or publish_time is null)") - not_exercise_ids = not_exercise_ids.blank? ? "(-1)" : "(" + not_exercise_ids.map(&:exercise_id).join(",") + ")" - exercise_num = course.exercises.where("publish_time <= '#{Time.now}' and id not in #{not_exercise_ids}").count - end - else - exercise_num = course.exercises.where("publish_time <= '#{Time.now}' and unified_setting = 1").count - end - exercise_num -end - -def visable_course_homework course, type=0, is_teacher, category_id - category_str = category_id.nil? ? "is null" : "= #{category_id}" - if is_teacher - if type != 0 - homework_num = course.homework_commons.where("homework_type = #{type} and course_homework_category_id #{category_str}").count - else - homework_num = course.homework_commons.where(:homework_type => [1,3,4]).count - end - elsif User.current.member_of_course?(course) - member = course.members.where(:user_id => User.current.id).first - if member.try(:course_group_id).to_i == 0 - if type != 0 - homework_num = course.homework_commons.where("homework_commons.homework_type = #{type} and publish_time <= '#{Time.now}' and unified_setting = 1 and course_homework_category_id #{category_str}").count - else - homework_num = course.homework_commons.where("homework_type in (1, 3, 4) and publish_time <= '#{Time.now}' and unified_setting = 1").count - end - else - not_homework_ids = course.homework_group_settings.where("course_group_id = #{member.try(:course_group_id)} and (publish_time > '#{Time.now}' or publish_time is null)") - not_homework_ids = not_homework_ids.blank? ? "(-1)" : "(" + not_homework_ids.map(&:homework_common_id).join(",") + ")" - if type != 0 - homework_num = course.homework_commons.where("homework_commons.homework_type = #{type} and publish_time <= '#{Time.now}' and id not in #{not_homework_ids} and course_homework_category_id #{category_str}").count - else - homework_num = course.homework_commons.where("homework_type in (1, 3, 4) and publish_time <= '#{Time.now}' and id not in #{not_homework_ids}").count - end - end - else - if type != 0 - homework_num = course.homework_commons.where("homework_type = #{type} and publish_time <= '#{Time.now}' and unified_setting = 1 and course_homework_category_id #{category_str}").count - else - homework_num = course.homework_commons.where("homework_type in (1, 3, 4) and publish_time <= '#{Time.now}' and unified_setting = 1").count - end - end - homework_num -end - -def visible_task_count course, is_teacher - task_count = 0 - if is_teacher - task_count = course.graduation_tasks.count - else - task_count = course.graduation_tasks.where("publish_time <= '#{Time.now}'").count - end - task_count -end - -def update_shixun_work_status homework - shixun = homework.shixuns.first - student_works = homework.student_works.where(:work_status => 0) - homework_challenge_settings = homework.homework_challenge_settings - challeng_ids = homework_challenge_settings.map(&:challenge_id) - # 取已发布的作品 - if homework.unified_setting - student_works = student_works - else - setting = homework.homework_group_settings.where("publish_time < '#{Time.now}'") - if setting.blank? - student_works = student_works.where("0=1") - else - users = homework.course.members.where(:course_group_id => setting.map(&:course_group_id)) - student_works = student_works.where(:user_id => users.map(&:user_id)) - end - end - # 已发布作品且状态为未提交的作品 如果有开启过实训则更新状态 - myshixuns = Myshixun.where(:shixun_id => shixun.id, :user_id => student_works.map(&:user_id)) - myshixuns.each do |myshixun| - work = student_works.where(:user_id => myshixun.user_id).first - member = Member.find_by_sql("select course_group_id from members where course_id = #{homework.course_id} and user_id = #{work.user_id}").first - setting_time = homework_group_setting homework, member.try(:course_group_id) - games = myshixun.games.where(:challenge_id => challeng_ids) - myshixun_endtime = games.select{|game| game.status == 2}.size == games.size ? games.map(&:end_time).max : nil - compelete_status = 0 - if myshixun_endtime.present? && myshixun_endtime < setting_time.end_time - if myshixun_endtime < setting_time.publish_time - compelete_status = 2 - else - compelete_status = 1 - end - end - if setting_time.end_time > Time.now - work.update_attributes(:work_status => 1, :late_penalty => 0, :commit_time => myshixun.updated_at, :update_time => myshixun.updated_at, :myshixun_id => myshixun.id, :compelete_status => compelete_status) - else - work.update_attributes(:work_status => ((myshixun.is_complete? && (myshixun.done_time < setting_time.end_time)) ? 1 : 2), :late_penalty => (myshixun.is_complete? && (myshixun.done_time < setting_time.end_time) ? 0 : homework.late_penalty), :commit_time => myshixun.updated_at, :update_time => myshixun.updated_at, :myshixun_id => myshixun.id, :compelete_status => compelete_status) - end - set_shixun_final_score work, homework.homework_detail_manual.answer_open_evaluation, homework_challenge_settings - end - # 更新所有学生的效率分 - update_student_eff_score HomeworkCommon.where(:id => homework.id).first -=begin - student_works.each do |work| - if work.work_status == 0 - myshixun = Myshixun.where(:shixun_id => shixun.id, :user_id => work.user_id).first - if myshixun - member = Member.find_by_sql("select course_group_id from members where course_id = #{homework.course_id} and user_id = #{User.current.id}").first - setting_time = homework_group_setting homework, member.try(:course_group_id) - if setting_time.end_time > Time.now - work.update_attributes(:work_status => 1, :late_penalty => 0, :commit_time => myshixun.updated_at, :update_time => myshixun.updated_at, :myshixun_id => myshixun.id) - else - work.update_attributes(:work_status => ((myshixun.is_complete? && (myshixun.done_time < setting_time.end_time)) ? 1 : 2), :late_penalty => (myshixun.is_complete? && (myshixun.done_time < setting_time.end_time) ? 0 : homework.late_penalty), :commit_time => myshixun.updated_at, :update_time => myshixun.updated_at, :myshixun_id => myshixun.id) - end - end - end - set_shixun_final_score work, homework.homework_detail_manual.answer_open_evaluation, homework_challenge_settings - end -=end -end - -#成绩计算 -def set_final_score homework,student_work - if homework && homework.homework_detail_manual && !student_work.ultimate_score - if !homework.homework_detail_manual.final_mode - tea_ass_proportion = homework.homework_detail_manual.ta_proportion - tea_proportion = homework.homework_detail_manual.te_proportion - if homework.homework_type != 2 #非编程作业 - if student_work.teacher_score - if student_work.teaching_asistant_score.nil? - if student_work.student_score.nil? - student_work.final_score = student_work.teacher_score - else - te_proportion = tea_proportion + tea_ass_proportion / 2 - final_te_score = BigDecimal.new("#{student_work.teacher_score}") * BigDecimal.new("#{te_proportion}") - final_s_score = BigDecimal.new("#{student_work.student_score}") * (BigDecimal.new('1.0') - BigDecimal.new("#{te_proportion}")) - final_score = final_te_score + final_s_score - student_work.final_score = format("%.2f",final_score.to_f) - end - else - if student_work.student_score.nil? - te_proportion = tea_proportion + (1.0 - tea_proportion - tea_ass_proportion) / 2 - final_te_score = BigDecimal.new("#{student_work.teacher_score}") * BigDecimal.new("#{te_proportion}") - final_ta_score = BigDecimal.new("#{student_work.teaching_asistant_score}") * (BigDecimal.new('1.0') - BigDecimal.new("#{te_proportion}")) - final_score = final_te_score + final_ta_score - student_work.final_score = format("%.2f",final_score.to_f) - else - final_te_score = BigDecimal.new("#{student_work.teacher_score}") * BigDecimal.new("#{tea_proportion}") - final_ta_score = BigDecimal.new("#{student_work.teaching_asistant_score}") * BigDecimal.new("#{tea_ass_proportion}") - final_s_score = BigDecimal.new("#{student_work.student_score}") * (BigDecimal.new('1.0') - BigDecimal.new("#{tea_proportion}") - BigDecimal.new("#{tea_ass_proportion}")) - final_score = final_te_score + final_ta_score + final_s_score - student_work.final_score = format("%.2f",final_score.to_f) - end - end - else - if student_work.teaching_asistant_score.nil? - student_work.final_score = student_work.student_score - elsif student_work.student_score.nil? - student_work.final_score = student_work.teaching_asistant_score - else - ta_proportion = tea_ass_proportion + tea_proportion / 2 - final_ta_score = BigDecimal.new("#{student_work.teaching_asistant_score}") * BigDecimal.new("#{ta_proportion}") - final_s_score = BigDecimal.new("#{student_work.student_score}") * (BigDecimal.new('1.0') - BigDecimal.new("#{ta_proportion}")) - final_score = final_ta_score + final_s_score - student_work.final_score = format("%.2f",final_score.to_f) - end - end - elsif homework.homework_type == 2 && homework.homework_detail_programing #编程作业-----设定:系统评分必定不为空 - #if homework.teacher_priority == 1 #教师优先 - sy_proportion = homework.homework_detail_programing.ta_proportion - if student_work.teacher_score - if student_work.teaching_asistant_score.nil? #教辅未评分 - if student_work.student_score.nil? - ta_proportion = tea_proportion + (1 - tea_proportion - sy_proportion) / 2 - final_te_score = BigDecimal.new("#{student_work.teacher_score}") * BigDecimal.new("#{ta_proportion}") - final_sy_score = BigDecimal.new("#{student_work.system_score || 0}") * (BigDecimal.new('1.0') - BigDecimal.new("#{ta_proportion}")) - final_score = final_sy_score + final_te_score - student_work.final_score = format("%.2f",final_score.to_f) - else - rest_proportion = tea_ass_proportion / 3 - final_sy_score = BigDecimal.new("#{student_work.system_score || 0}") * BigDecimal.new("#{sy_proportion + rest_proportion}") - final_te_score = BigDecimal.new("#{student_work.teacher_score}") * BigDecimal.new("#{tea_proportion + rest_proportion}") - final_st_score = BigDecimal.new("#{student_work.student_score}") * (BigDecimal.new('1.0') - BigDecimal.new("#{sy_proportion + rest_proportion}") - BigDecimal.new("#{tea_proportion + rest_proportion}")) - final_score = final_sy_score + final_te_score + final_st_score - student_work.final_score = format("%.2f",final_score.to_f) - end - elsif student_work.student_score.nil? #学生未评分 - rest_proportion = (1 - tea_proportion - sy_proportion - tea_ass_proportion) / 3 - final_sy_score = BigDecimal.new("#{student_work.system_score || 0}") * BigDecimal.new("#{sy_proportion + rest_proportion}") - final_te_score = BigDecimal.new("#{student_work.teacher_score}") * BigDecimal.new("#{tea_proportion + rest_proportion}") - final_ta_score = BigDecimal.new("#{student_work.teaching_asistant_score}") * (BigDecimal.new('1.0') - BigDecimal.new("#{sy_proportion + rest_proportion}") - BigDecimal.new("#{tea_proportion + rest_proportion}")) - final_score = final_sy_score + final_te_score + final_ta_score - student_work.final_score = format("%.2f",final_score.to_f) - else - final_sy_score = BigDecimal.new("#{student_work.system_score || 0}") * BigDecimal.new("#{sy_proportion}") - final_te_score = BigDecimal.new("#{student_work.teacher_score}") * BigDecimal.new("#{tea_proportion}") - final_ta_score = BigDecimal.new("#{student_work.teaching_asistant_score}") * BigDecimal.new("#{tea_ass_proportion}") - final_s_score = BigDecimal.new("#{student_work.student_score}") * (BigDecimal.new('1.0') - BigDecimal.new("#{sy_proportion}") - BigDecimal.new("#{tea_proportion}") - BigDecimal.new("#{tea_ass_proportion}")) - final_score = final_sy_score + final_ta_score + final_te_score + final_st_score - student_work.final_score = format("%.2f",final_score.to_f) - end - else - if student_work.teaching_asistant_score.nil? #教辅未评分 - if student_work.student_score.nil? - student_work.final_score = student_work.system_score - else - ta_proportion = sy_proportion + (tea_ass_proportion + tea_proportion) / 2 - final_sy_score = BigDecimal.new("#{student_work.system_score || 0}") * BigDecimal.new("#{ta_proportion}") - final_st_score = BigDecimal.new("#{student_work.student_score}") * (BigDecimal.new('1.0') - BigDecimal.new("#{ta_proportion}")) - final_score = final_sy_score + final_st_score - student_work.final_score = format("%.2f",final_score.to_f) - end - elsif student_work.student_score.nil? #学生未评分 - if student_work.teaching_asistant_score.nil? - student_work.final_score = student_work.system_score - else - ta_proportion = sy_proportion + (1.0 - tea_ass_proportion - sy_proportion) / 2 - final_sy_score = BigDecimal.new("#{student_work.system_score || 0}") * BigDecimal.new("#{ta_proportion}") - final_ts_score = BigDecimal.new("#{student_work.teaching_asistant_score}") * (BigDecimal.new('1.0') - BigDecimal.new("#{ta_proportion}")) - final_score = final_sy_score + final_ts_score - student_work.final_score = format("%.2f",final_score.to_f) - end - else - rest_proportion = tea_proportion / 3 - final_sy_score = BigDecimal.new("#{student_work.system_score || 0}") * BigDecimal.new("#{sy_proportion + rest_proportion}") - final_ts_score = BigDecimal.new("#{student_work.teaching_asistant_score}") * BigDecimal.new("#{tea_ass_proportion + rest_proportion}") - final_st_score = BigDecimal.new("#{student_work.student_score}") * (BigDecimal.new('1.0') - BigDecimal.new("#{sy_proportion + rest_proportion}") - BigDecimal.new("#{tea_ass_proportion + rest_proportion}")) - final_score = final_sy_score + final_ts_score + final_st_score - student_work.final_score = format("%.2f",final_score.to_f) - end - end - end - else - if homework.homework_type != 2 - if student_work.teacher_score - student_work.final_score = student_work.teacher_score - else - if student_work.teaching_asistant_score.nil? - student_work.final_score = student_work.student_score - else - student_work.final_score = student_work.teaching_asistant_score - end - end - elsif homework.homework_type == 2 && homework.homework_detail_programing - if student_work.teacher_score - student_work.final_score = student_work.teacher_score - else - if student_work.teaching_asistant_score - student_work.final_score = student_work.teaching_asistant_score - else - if student_work.system_score - student_work.final_score = student_work.system_score - else - student_work.final_score = student_work.student_score - end - end - end - end - end - if student_work.final_score - score = student_work.final_score - student_work.absence_penalty - student_work.late_penalty - student_work.appeal_penalty - student_work.work_score = format("%.2f",(score < 0 ? 0 : score).to_f) if score - else - student_work.work_score = nil - end - end -end - -# 计算实训作品学生的效率分 -def update_student_eff_score homework - if homework.work_efficiency && homework.max_efficiency != 0 - homework.student_works.where("compelete_status != 0").each do |student_work| - eff_score = student_work.efficiency / homework.max_efficiency * homework.eff_score - student_work.eff_score = format("%.2f", eff_score) - unless student_work.ultimate_score - work_score = student_work.final_score + student_work.eff_score - student_work.late_penalty - student_work.work_score = format("%.2f", work_score < 0 ? 0 : work_score) - end - student_work.save - end - else - homework.student_works.where("compelete_status != 0").each do |student_work| - student_work.eff_score = 0 - unless student_work.ultimate_score - work_score = student_work.final_score + student_work.eff_score - student_work.late_penalty - student_work.work_score = format("%.2f", work_score < 0 ? 0 : work_score) - end - student_work.save - end - end -end - -# 实训作业的评分 -def set_shixun_final_score student_work, answer_open_evaluation, homework_challenge_settings - unless student_work.work_status == 0 - myshixun = student_work.myshixun - final_score = 0 - compelete = true - max_endtime = "" - user_total_score = 0 - pass_consume_time = 0 - homework_challenge_settings.each do |setting| - game = myshixun.games.where(:challenge_id => setting.challenge_id, :status => 2).first - unless game.nil? - pass_consume_time += (game.cost_time / 60.0).to_f - user_total_score += game.final_score.to_i < 0 ? 0 : game.challenge.score.to_i - adjust_score = student_work.challenge_work_scores.where(:challenge_id => setting.challenge_id).last - final_score += adjust_score.present? ? adjust_score.score : (answer_open_evaluation ? setting.score : (game.final_score >= 0 ? setting.score : 0)) - max_endtime = max_endtime == "" ? game.end_time : (game.end_time > max_endtime ? game.end_time : max_endtime) - else - compelete = false - end - end - - efficiency = (pass_consume_time == 0 ? 0 : Math.log((user_total_score / pass_consume_time.to_f) + 1.0)) - student_work.efficiency = efficiency < 0 ? 0 : format("%.2f", efficiency) - - if compelete && max_endtime != "" - homework = student_work.homework_common - member = Member.find_by_sql("select course_group_id from members where course_id = #{homework.course_id} and user_id = #{student_work.user_id}").first - setting_time = homework_group_setting homework, member.try(:course_group_id) - if setting_time.publish_time.present? && setting_time.end_time.present? - if max_endtime < setting_time.publish_time - student_work.compelete_status = 2 - else - if max_endtime < setting_time.end_time || (homework.allow_late && (homework.course.end_date.nil? || max_endtime < homework.course.end_date.end_of_day)) - student_work.compelete_status = 1 - student_work.cost_time = max_endtime.to_i - setting_time.publish_time.to_i - else - student_work.compelete_status = 0 - end - end - end - - if homework.work_efficiency - if homework.max_efficiency < student_work.efficiency - homework.max_efficiency = student_work.efficiency - homework.update_column("max_efficiency", homework.max_efficiency) - end - eff_score = homework.max_efficiency == 0 ? 0 : student_work.efficiency / homework.max_efficiency * homework.eff_score - student_work.eff_score = format("%.2f", eff_score) - else - student_work.eff_score = 0 - end - elsif !compelete - student_work.compelete_status = 0 - end - student_work.final_score = format("%.2f", final_score.to_f) - score = student_work.final_score + student_work.eff_score - student_work.late_penalty - student_work.work_score = format("%.2f", score < 0 ? 0 : score.to_f) unless student_work.ultimate_score - student_work.save! - end -end - -# 用户评测时更新实训作业成绩 -def update_myshixun_work_score myshixun - ActiveRecord::Base.transaction do - student_works = myshixun.student_works - #logger.info("#############student_works_count: #{student_works.count}") - if student_works.count > 0 - student_works.each do |work| - homework = work.homework_common - member = Member.find_by_sql("select course_group_id from members where course_id = #{homework.course_id} and user_id = #{User.current.id}").first - #logger.info("#############member_course_group_id: #{member.try(:course_group_id)}") - setting_time = homework_group_setting homework, member.try(:course_group_id) - if setting_time.end_time.present? && (setting_time.end_time > Time.now || (homework.allow_late && !homework.course.is_end)) - #logger.info("#############setting_time: #{setting_time.end_time}") - - user_total_score = 0 - pass_consume_time = 0 - final_score = 0 - homework.homework_challenge_settings.each do |setting| - game = myshixun.games.where(:challenge_id => setting.challenge_id, :status => 2).first - unless game.nil? - pass_consume_time += (game.cost_time / 60.0).to_f - user_total_score += game.final_score.to_i < 0 ? 0 : game.challenge.score.to_i - adjust_score = work.challenge_work_scores.where(:challenge_id => setting.challenge_id).last - final_score += adjust_score.present? ? adjust_score.score : (homework.homework_detail_manual.answer_open_evaluation ? setting.score : (game.final_score >= 0 ? setting.score : 0)) - end - end - if work.work_status == 0 - is_complete = myshixun.is_complete? && (myshixun.done_time < setting_time.end_time) - work.work_status = setting_time.end_time > Time.now ? 1 : (is_complete ? 1 : 2) - work.late_penalty = setting_time.end_time > Time.now ? 0 : (is_complete ? 0 : homework.late_penalty) - work.commit_time = myshixun.created_at > setting_time.publish_time ? setting_time.publish_time : myshixun.created_at - work.myshixun_id = myshixun.id - end - - efficiency = (pass_consume_time == 0 ? 0 : Math.log((user_total_score / pass_consume_time.to_f) + 1.0)) - work.efficiency = format("%.2f", efficiency) - - games = myshixun.games.where(:challenge_id => homework.homework_challenge_settings.map(&:challenge_id)) - myshixun_endtime = games.select{|game| game.status == 2}.size == games.size ? games.map(&:end_time).max : nil - if myshixun_endtime.present? - min_efficiency_changed = min_efficiency_changed.present? ? min_efficiency_changed : false - work.compelete_status = 1 - work.cost_time = myshixun_endtime.to_i - setting_time.publish_time.to_i - - # 计算作品的效率分(已完成才计算) - if homework.work_efficiency - # 如果作业的最大效率值有变更则更新所有作品的效率分 - if homework.max_efficiency < work.efficiency - homework.max_efficiency = work.efficiency - homework.update_column("max_efficiency", homework.max_efficiency) - update_student_eff_score homework - end - eff_score = homework.max_efficiency == 0 ? 0 : work.efficiency / homework.max_efficiency * homework.eff_score - work.eff_score = format("%.2f", eff_score) - end - end - - work.update_time = Time.now - - # 为迁移的数据做特殊处理, 若分数小于当前通关分数则不更新 - work.final_score = final_score if work.final_score.nil? || final_score > work.final_score - score = work.final_score + work.eff_score - work.late_penalty - work.work_score = format("%.2f",(score < 0 ? 0 : score).to_f) unless work.ultimate_score - #logger.info("#############work_score: #{score}") - work.save! - end - end - end - end -end - -# 用户开启实训时更新作品状态 -def update_myshixun_work_status myshixun - student_works = StudentWork.find_by_sql("SELECT sw.* FROM student_works sw, homework_commons_shixuns hcs WHERE sw.user_id = #{User.current.id} AND sw.`homework_common_id` = hcs.`homework_common_id` AND hcs.`shixun_id` = #{myshixun.shixun_id} and sw.work_status = 0") - logger.info("#############student_works_count: #{student_works.count}") - if student_works.count > 0 - student_works.each do |work| - homework = work.homework_common - member = Member.find_by_sql("select course_group_id from members where course_id = #{homework.course_id} and user_id = #{User.current.id}").first - setting_time = homework_group_setting homework, member.try(:course_group_id) - if setting_time.end_time.present? && (setting_time.end_time > Time.now || (homework.allow_late && !homework.course.is_end)) - logger.info("#############setting_time: #{setting_time.end_time}") - work.work_status = setting_time.end_time > Time.now ? 1 : 2 - work.late_penalty = setting_time.end_time > Time.now ? 0 : homework.late_penalty - work.update_time = Time.now - work.commit_time = Time.now - work.myshixun_id = myshixun.id - work.save - end - end - end -end - -def quote_resource_bank resource, course - atta = Attachment.new(:filename => resource.filename, :disk_filename => resource.disk_filename, :filesize => resource.filesize, :digest => resource.digest, :downloads => 0, :is_publish => 0, - :author_id => User.current.id, :description => resource.description, :disk_directory => resource.disk_directory, :is_public => 0, :copy_from => resource.copy_from.nil? ? resource.id : resource.copy_from, - :quotes => 0, :resource_bank_id => resource.id, :created_on => Time.now, :content_type =>resource.content_type) - if course.attachments << atta - # 更新引用次数 - quotes = resource.quotes.to_i + 1 - resource.update_attribute(:quotes, quotes) - end -end - -def quote_homework_bank homework, course - ActiveRecord::Base.transaction do - new_homework = HomeworkCommon.new(:name => homework.name, :user_id => User.current.id, :description => homework.description, :homework_type => homework.homework_type, :late_penalty => 5, - :course_id => course.id, :teacher_priority => 1, :anonymous_comment => 1, :quotes => 0, :is_open => 0, :homework_bank_id => homework.id, :score_open => 1, - :anonymous_appeal => 0, :is_public => 0, :reference_answer => homework.reference_answer, :answer_public => 1, :allow_late => 1) - - new_homework.homework_detail_manual = HomeworkDetailManual.new - new_homework_detail_manual = new_homework.homework_detail_manual - new_homework_detail_manual.te_proportion = 1.0 - new_homework_detail_manual.ta_proportion = 0 - new_homework_detail_manual.comment_status = 0 - - new_homework_detail_manual.evaluation_num = 0 - new_homework_detail_manual.absence_penalty = 0 - - if new_homework.homework_type == 2 - new_homework.homework_detail_programing = HomeworkDetailPrograming.new - new_homework.homework_detail_programing.ta_proportion = 0 - new_homework.homework_detail_programing.language = homework.language - homework.homework_bank_tests.each_with_index do |homework_test| - new_homework.homework_tests << HomeworkTest.new( - input: homework_test.input, - output: homework_test.output - ) - end - homework.homework_bank_samples.each_with_index do |homework_test| - new_homework.homework_samples << HomeworkSample.new( - input: homework_test.input, - output: homework_test.output - ) - end - end - - if new_homework.homework_type == 3 - new_homework.homework_detail_group = HomeworkDetailGroup.new - new_homework.homework_detail_group.min_num = homework.min_num - new_homework.homework_detail_group.max_num = homework.max_num - new_homework.homework_detail_group.base_on_project = homework.base_on_project - end - - homework.attachments.each do |attachment| - att = attachment.copy - att.container_id = nil - att.container_type = nil - att.author_id = homework.user_id - att.copy_from = attachment.id - att.save - new_homework.attachments << att - end - - if new_homework.save - if new_homework.homework_type == 4 - HomeworkCommonsShixuns.create(:homework_common_id => new_homework.id, :shixun_id => homework.homework_bank_shixun.shixun_id) - end - new_homework_detail_manual.save if new_homework_detail_manual - new_homework.homework_detail_programing.save if new_homework.homework_detail_programing - new_homework.homework_detail_group.save if new_homework.homework_detail_group - create_works_list new_homework - - homework.update_column(:quotes, homework.quotes+1) - QuestionBank.where(:container_id => homework.id, :container_type => ["Common", "Shixun", "Group"]).update_all(:quotes => homework.quotes) - end - return new_homework - end -end - -def quote_exercise_bank exercise, course - ActiveRecord::Base.transaction do - new_exercise = Exercise.new(:exercise_name => exercise.name, :exercise_description => exercise.description, :user_id => User.current.id, :is_public => 0, - :exercise_status => 1, :show_result => 1, :course_id => course.id, :time => -1, :exercise_bank_id => exercise.id) - - exercise.exercise_bank_questions.each do |q| - option = { - :question_title => q[:question_title], - :question_type => q[:question_type] || 1, - :question_number => q[:question_number], - :question_score => q[:question_score], - :shixun_id => q[:shixun_id] - } - exercise_question = new_exercise.exercise_questions.new option - - if q.question_type != 5 - for i in 1..q.exercise_bank_choices.count - choice_option = { - :choice_position => i, - :choice_text => q.exercise_bank_choices[i-1][:choice_text] - } - exercise_question.exercise_choices.new choice_option - end - - for i in 1..q.exercise_bank_standard_answers.count - standard_answer_option = { - :exercise_choice_id => q.exercise_bank_standard_answers[i-1][:exercise_bank_choice_id], - :answer_text => q.exercise_bank_standard_answers[i-1][:answer_text] - } - exercise_question.exercise_standard_answers.new standard_answer_option - end - else - for i in 1..q.exercise_bank_shixun_challenges.count - challenge_option = { - :position => i, - :challenge_id => q.exercise_bank_shixun_challenges[i-1][:challenge_id], - :shixun_id => q.exercise_bank_shixun_challenges[i-1][:shixun_id], - :question_score => q.exercise_bank_shixun_challenges[i-1][:question_score] - } - exercise_question.exercise_shixun_challenges.new challenge_option - end - end - end - if new_exercise.save - create_exercises_list new_exercise - exercise.update_column(:quotes, exercise.quotes+1) - QuestionBank.where(:container_id => exercise.id, :container_type => "Exercise").update_all(:quotes => exercise.quotes) - end - return new_exercise - end -end - -def quote_poll_bank poll, course - ActiveRecord::Base.transaction do - new_poll = Poll.new(:polls_name => poll.name, :polls_description => poll.description, :user_id => User.current.id, :is_public => 0, - :polls_status => 1, :show_result => 1, :polls_type => 'Course', :course_id => course.id, :exercise_bank_id => poll.id) - - poll.exercise_bank_questions.each do |q| - option = { - :question_title => q[:question_title], - :question_type => q[:question_type] || 1, - :is_necessary => q[:is_necessary], - :question_number => q[:question_number], - :max_choices => q[:max_choices], - :min_choices => q[:min_choices] - } - poll_question = new_poll.poll_questions.new option - - for i in 1..q.exercise_bank_choices.count - choice_option = { - :answer_position => i, - :answer_text => q.exercise_bank_choices[i-1][:choice_text] - } - poll_question.poll_answers.new choice_option - end - end - if new_poll.save - create_polls_list new_poll - poll.update_column(:quotes, poll.quotes+1) - QuestionBank.where(:container_id => poll.id, :container_type => "Poll").update_all(:quotes => poll.quotes) - end - return new_poll - end -end - -def major_level_option - content = [] - option0 = [] - option0 << "选择课程所属专业层级" - option0 << 0 - option1 = [] - option1 << "专科" - option1 << 3 - option2 = [] - option2 << "本科" - option2 << 2 - option3 = [] - option3 << "研究生" - option3 << 1 - content << option0 - content << option1 - content << option2 - content << option3 - content -end - -def discipline_category_option major_level = 3 - content = [] - option0 = [] - option0 << "选择课程所属学科门类" - option0 << 0 - content << option0 - DisciplineCategory.where(:major_level => major_level).each do |dis| - option = [] - option << dis.name.to_s - option << dis.id - content << option - end - content -end - -def first_level_discipline_option disc_ca = 27 - content = [] - option0 = [] - option0 << "选择课程所属一级学科" - option0 << 0 - content << option0 - FirstLevelDiscipline.where(:discipline_category_id => disc_ca).each do |fir_dis| - option = [] - option << fir_dis.name.to_s - option << fir_dis.id - content << option - end - content -end - -def syllabus_major_option fir_dis = 213 - content = [] - option0 = [] - option0 << "选择课程所属专业" - option0 << 0 - content << option0 - Major.where(:first_level_discipline_id => fir_dis).each do |major| - option = [] - option << major.name.to_s - option << major.id - content << option - end - content -end - -def convert_to_char(str) - result = "" - length = str.length - unless str.nil? - if length === 1 - result += (str.to_i + 64).chr - return result - elsif length > 1 - for i in 0...length - result += (str[i].to_i + 64).chr - end - return result - end - end - return result -end - -def convert_to_chi_num num - result = "" - case num.to_i - when 1 - result = '一' - when 2 - result = '二' - when 3 - result = '三' - when 4 - result = '四' - when 5 - result = '五' - when 6 - result = '六' - when 7 - result = '七' - when 8 - result = '八' - when 9 - result = '九' - end - return result -end - -#根据条件过滤作业结果 -def search_work_member works,name - if name == "" - select_works = works - else - name = name.downcase - select_works = works.select{ |work| work.user.user_extensions[:student_id].to_s.downcase.include?(name) || (work.user[:lastname].to_s.downcase + work.user[:firstname].to_s.downcase).include?(name) - } - end - select_works -end - -# 作业的分班设置时间 -def homework_group_setting homework, group_id - setting = nil - if homework.homework_group_settings.where(:course_group_id => group_id).first - setting = homework.homework_group_settings.where(:course_group_id => group_id).first - else - setting = homework - end - setting -end - -# 试卷的分班设置时间 -def exercise_group_setting exercise, group - setting = nil - if exercise.exercise_group_settings.where(:course_group_id => group.try(:id)).first - setting = exercise.exercise_group_settings.where(:course_group_id => group.id).first - else - setting = exercise - end - setting -end - -# 问卷的分班设置时间 -def poll_group_setting poll, group - setting = nil - if poll.poll_group_settings.where(:course_group_id => group.try(:id)).first - setting = poll.poll_group_settings.where(:course_group_id => group.id).first - else - setting = poll - end - setting -end - -# 资源的分班设置时间 -def attacment_group_setting attachment, group - setting = nil - if attachment.attachment_group_settings.where(:course_group_id => group.try(:id)).first - setting = attachment.attachment_group_settings.where(:course_group_id => group.id).first - else - setting = attachment - end - setting -end - -#统计答题百分比,统计结果保留两位小数 -def statistics_result_percentage(e, t) - e = e.to_f - t = t.to_f - t == 0 ? 0 : format("%.1f", e*100/t) -end - -def subject_data subject - result = {} - subject_choices = 0 - subject_shixuns = 0 - subject_score = 0 - subject.stage_shixuns.each do |stage_shixun| - shixun = stage_shixun.shixun - subject_choices += shixun.challenges.where(:st => [1, 2]).count - subject_shixuns += shixun.challenges.where(:st => 0).count - subject_score += shixun.shixun_score - end - result[:subject_choices] = subject_choices - result[:subject_shixuns] = subject_shixuns - result[:subject_score] = subject_score - result -end - - -def tiding_url tiding - case tiding.container_type - when "ApplyUserAuthentication" - if tiding.tiding_type == "Apply" - tiding.container.auth_type == 1 ? identity_authentication_managements_path : professional_authentication_managements_path - else - tiding.container.auth_type == 1 ? authentication_account_path : professional_certification_account_path - end - when "CancelUserAuthentication" - authentication_account_path - when "CancelUserProCertification" - professional_certification_account_path - when "ApplyAddDepartment" - tiding.tiding_type == "Apply" ? depart_managements_path() : my_account_path() - when "ApplyAddSchools" - tiding.tiding_type == "Apply" ? unit_managements_path() : my_account_path() - when "ApplyAction" - tiding.tiding_type == "System" ? (tiding.parent_container_type == "ApplyShixun" ? shixun_path(Shixun.find(tiding.parent_container_id).identifier):(tiding.parent_container_type == "TrialAuthorization" ? user_path(tiding.user_id) : subject_path(tiding.parent_container_id))):(tiding.parent_container_type == "ApplyShixun" ? shixun_authorization_managements_path():(tiding.parent_container_type == "TrialAuthorization"? trial_authorization_managements_path(): subject_authorization_managements_path())) - when 'JoinCourse' - course_path(tiding.container_id, :type => "JoinCourse") - when 'StudentJoinCourse', 'DealCourse', 'TeacherJoinCourse' - course_path(tiding.container_id) - when 'Course', 'ArchiveCourse' - course_path(tiding.container_id) - when 'Shixun' - '/shixuns/' + tiding.container.identifier - when 'Subject' - '/paths/' + tiding.container_id.to_s - when 'JournalsForMessage' - case tiding.parent_container_type - when "Principal" - feedback_path(tiding.parent_container_id) - when "HomeworkCommon" - student_work_index_path(:homework => tiding.parent_container_id, :tab => 2) - when "GraduationTopic" - graduation_topic_path(tiding.parent_container_id, :tab => 2) - when "StudentWorksScore" - student_work_path(:id => tiding.container.try(:jour).try(:student_work_id)) - end - when 'Message' - board_message_path(tiding.container.board_id, tiding.parent_container_id) - when 'Memo' - forum_path(tiding.parent_container_id) - when 'Watcher' - user_path(tiding.trigger_user_id) - when 'PraiseTread' - try = tiding.parent_container_type.constantize - object = try.find(tiding.parent_container_id) - case tiding.parent_container_type - when "Challenge" - myshixun_id = Myshixun.where(:user_id => tiding.trigger_user_id, :shixun_id => Challenge.find(tiding.parent_container_id).shixun_id).first - myshixun_game_path(Game.where(:myshixun_id => myshixun_id.id, :challenge_id => tiding.parent_container_id).first, :myshixun_id => myshixun_id) - when "Discuss" - myshixun_game_path(object.user_game, :myshixun_id => object.user_myshixun) - when "Message" - object.parent.present? ? board_message_path(object.board_id, object.root_id) : board_message_path(object.board_id, object) - when "Memo" - object.parent.present? ? forum_path(object.root_id) : forum_path(object) - when "JournalsForMessage" - case object.jour_type - when "Principal" - feedback_path(object.jour_id) - when "HomeworkCommon" - student_work_index_path(:homework => object.jour_id, :tab => 2) - when "StudentWorksScore" - student_work_path(:id => object.try(:jour).try(:student_work_id)) - end - when "HomeworkCommon" - student_work_index_path(:homework => tiding.parent_container_id, :tab => 2) - when "Issue" - issue_path(tiding.parent_container_id) - when "Journal" - issue_path(object.journalized_id) - end - when 'Discuss' - shixun_discuss_shixun_path(tiding.container.dis) - when 'Grade' - user_grade_user_path(User.current) - when 'JoinProject' - project_path(tiding.container_id, :type => "applied_project") - when 'ReporterJoinProject', 'DealProject', 'ManagerJoinProject' - project_path(tiding.container_id) - when 'Poll' - case tiding.parent_container_type - when 'CommitPoll' - student_poll_list_poll_path(tiding.container, :tab => 2) - else - student_poll_list_poll_path(tiding.container) - end - when 'Exercise' - case tiding.parent_container_type - when 'CommitExercise', 'ExerciseScore' - show_student_result_exercise_path(tiding.container,:user_id => tiding.trigger_user_id) - else - student_exercise_list_exercise_path(tiding.container) - end - when 'StudentGraduationTopic', 'DealStudentTopicSelect' - graduation_topic_path(tiding.parent_container_id) - when 'GraduationTask' - graduation_task_path(tiding.container_id) - when 'GraduationWork' - graduation_work_path(tiding.container_id) - when 'GraduationWorkScore' - graduation_work_path(tiding.parent_container_id) - when 'HomeworkCommon' - case tiding.parent_container_type - when 'AnonymousCommentFail' - student_work_index_path(:homework => tiding.container_id, :tab => 4) - when 'HomeworkPublish' - student_work_index_path(:homework => tiding.container_id, :tab => 2) - when 'AnonymousAppeal' - work = tiding.container.student_works(:user_id => User.current.id).first - work.present? ? student_work_path(work.try(:id)) : "javascript:void(0)" - else - student_work_index_path(:homework => tiding.container_id) - end - when 'StudentWork' - student_work_path(tiding.container_id) - when 'StudentWorksScore', 'StudentWorksScoresAppeal' - student_work_path(tiding.parent_container_id) - when 'ChallengeWorkScore' - homework_common_path(tiding.container.try(:student_work).try(:homework_common_id)) - when 'SendMessage' - mirror_repository_managements_path - when 'Journal' - issue_path(tiding.parent_container_id) - when 'Issue' - issue_path(tiding.container_id) - when 'PullRequest' - project_pull_requests_path(tiding.parent_container_id) - when 'Department' - my_account_path - end -end - -def create_shixun_homework_cha_setting homework, shixun - if shixun.present? - sum_score = 0 - total_score = 100.0 - homework.eff_score - shixun.challenges.each_with_index do |challeng, index| - if index < shixun.challenges.length - 1 - score = ((total_score / shixun.challenges.length) * total_score).floor / total_score - sum_score += score - else - score = total_score - sum_score - end - HomeworkChallengeSetting.create(:homework_common_id => homework.id, :challenge_id => challeng.id, :shixun_id => shixun.id, :score => score) - end - end -end +# encoding: utf-8 +# +# Redmine - project management software +# Copyright (C) 2006-2013 Jean-Philippe Lang +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +require 'forwardable' +require 'cgi' +require 'iconv' +module ApplicationHelper + include Redmine::WikiFormatting::Macros::Definitions + include Redmine::I18n + include GravatarHelper::PublicMethods + include Redmine::Pagination::Helper + include AvatarHelper + ## added by william + include PraiseTreadHelper + include CoursesHelper + + extend Forwardable + def_delegators :wiki_helper, :wikitoolbar_for, :heads_for_wiki_formatter + + # 课堂相关controller + def course_controller + ["courses", "homework_common", "student_work", "exercise", "poll", "boards", "messages", "graduation_topics", "graduation_tasks", + "graduation_works", "files"] + end + + # 实训课程相关controller + def subjects_controller + ["subjects", "stages"] + end + + # 实训路径相关controller + def shixuns_controller + ["shixuns", "challenges", "myshixuns", "games"] + end + + # 工程认证相关controller + def ecs_controller + ["ecs", "ec_courses", "ec_course_evaluations", "ec_course_supports", "ec_course_targets", "ec_graduation_requirements", + "ec_major_schools", "ec_majors", "ec_years"] + end + + def exercise_bank_json_data exercises + exercises.map do |exercise| + exercise_path = exercise_bank_path(exercise) + course_list = exercise.course_list.name + user_name = exercise.user.show_real_name + user_path = user_path(exercise.user) + exercise.attributes.dup.except("description", "is_public", "quotes", "container_id", "container_type", "created_at", "updated_at").merge({ + user_name: user_name, + user_path: user_path, + course_list: course_list, + exercise_path: exercise_path + }) + end + end + + def ac_pass?(standard_value, real_value) + standard_value && real_value && real_value >= standard_value ? "达成" : "未达成" + end + + def ec_pass?(standard_value, real_value) + standard_value && real_value && real_value >= standard_value ? 1 : 0 + end + + # 工程认证删除关联课堂 + def delete_course_correlation_ec_course_evaluations ec_course + ec_course_evaluations = ec_course.ec_course_evaluations.where(:is_course_type => true) + ec_course_evaluations.destroy_all if ec_course_evaluations + end + + def sync_ec_year_student_score ec_subitem, ce, year_students, students, works, position=1 + year_students.each do |year_student| + if students.map(&:id).include?(year_student.id) + work = works.where(:user_id => students.select{|s| s.id == year_student.id}[0].try(:user_id)).first + score = work.respond_to?(:work_score) ? work.try(:work_score) : work.try(:score) + else + score = 0 + end + ec_subitem.ec_student_achievements << EcStudentAchievement.new(:ec_year_student_id => year_student.id, :student_number => year_student.student_id, + :student_name => year_student.name, :score => score.to_f, + :position => position, :ec_course_evaluation_id => ce.id) + Rails.logger.info("############work_score:#{score}") + end + end + + # 同步在线课堂的考核标准和考核分项 + # ec_course: 工程认证的课程 + # course: 关联的在线课堂 + def sync_course_correlation_ec_course_evaluations ec_course, course + # 先删除之前的关联数据 + delete_course_correlation_ec_course_evaluations ec_course + + students = EcYearStudent.find_by_sql("SELECT eys.id, eys.student_id, eys.name, uxe.user_id FROM ec_year_students eys JOIN + (SELECT ue.student_id, ue.user_id FROM user_extensions ue JOIN students_for_courses sfc ON ue.`user_id` = sfc.`student_id` + WHERE sfc.`course_id` = #{course.id})uxe ON eys.student_id = uxe.student_id WHERE eys.ec_year_id = #{ec_course.ec_year_id}") + + year_students = ec_course.ec_year.ec_year_students + + # 实训作业模块 + shixun_models = course.homework_commons.where("homework_type = 4 and publish_time < '#{Time.now}'") + unless shixun_models.blank? + ce = EcCourseEvaluation.create(:name => "实训作业", :evluation_count => 1, :status => 2, :ec_course_id => ec_course.id, :is_course_type => true) + shixun_models.each do |shixun| + ec_subitem = EcCourseEvaluationSubitem.create(:name => shixun.name, :ec_course_evaluation_id => ce.id) + + sync_ec_year_student_score ec_subitem, ce, year_students, students, shixun.student_works + end + end + + # 普通作业模块 + common_models = course.homework_commons.where("homework_type = 1 and publish_time < '#{Time.now}'") + unless common_models.blank? + ce = EcCourseEvaluation.create(:name => "普通作业", :evluation_count => 1, :status => 2, :ec_course_id => ec_course.id, :is_course_type => true) + common_models.each do |common| + ec_subitem = EcCourseEvaluationSubitem.create(:name => common.name, :ec_course_evaluation_id => ce.id) + + sync_ec_year_student_score ec_subitem, ce, year_students, students, common.student_works + end + end + + # 分组作业模块 + group_models = course.homework_commons.where("homework_type = 3 and publish_time < '#{Time.now}'") + unless group_models.blank? + ce = EcCourseEvaluation.create(:name => "分组作业", :evluation_count => 1, :status => 2, :ec_course_id => ec_course.id, :is_course_type => true) + group_models.each do |group| + ec_subitem = EcCourseEvaluationSubitem.create(:name => group.name, :ec_course_evaluation_id => ce.id) + + sync_ec_year_student_score ec_subitem, ce, year_students, students, group.student_works + end + end + + # 试卷模块 + exercise_models = course.exercises.where("exercise_status > 1") + unless exercise_models.blank? + ce = EcCourseEvaluation.create(:name => "试卷", :evluation_count => 1, :status => 2, :ec_course_id => ec_course.id, :is_course_type => true) + exercise_models.each do |exercise| + ec_subitem = EcCourseEvaluationSubitem.create(:name => exercise.exercise_name, :ec_course_evaluation_id => ce.id) + + sync_ec_year_student_score ec_subitem, ce, year_students, students, exercise.exercise_users + end + end + + # 毕设任务模块 + task_models = course.graduation_tasks.where("publish_time < '#{Time.now}'") + unless task_models.blank? + ce = EcCourseEvaluation.create(:name => "毕设任务", :evluation_count => task_models.size, :status => 1, :ec_course_id => ec_course.id, :is_course_type => true) + task_models.each_with_index do |task, index| + ec_subitem = EcCourseEvaluationSubitem.create(:name => task.name, :ec_course_evaluation_id => ce.id) + + sync_ec_year_student_score ec_subitem, ce, year_students, students, task.graduation_works, index + 1 + end + end + end + + # 选用实训的学校情况 + def school_user_detail shixun + user_ids = shixun.myshixuns.pluck(:user_id) + schools = School.where(:id => UserExtensions.where(:user_id => user_ids).pluck(:school_id)) + school_size = schools.size + str = school_size > 0 ? "#{schools.limit(2).map(&:name).join("、")}等 #{school_size}所" : "0所" + end + + def shixun_json_data shixuns + shixuns.map do |shixun| + school_detail = school_user_detail shixun + preference = shixun.shixun_preference + shixun_path = shixun_path(shixun) + shixun.attributes.dup.merge({ + school_detail: school_detail, + preference: preference, + shixun_path: shixun_path + }) + end + end + + # 分班 + def member_group_name members, user_id + member = members.where(:user_id => user_id).first + group_name = member.try(:course_group_id).to_i == 0 ? '未分班' : member.course_group.name + end + + # 分班 + def new_member_group_name course_id, user_id + group_id = Member.where(:course_id => course_id, :user_id => user_id).pluck(:course_group_id).first + group_id == 0 ? '未分班' : CourseGroup.where(:id => group_id).pluck(:name).first + end + + # 分班id + def member_group_id members, user_id + member = members.where(:user_id => user_id).first + group_id = member.try(:course_group_id).to_i + end + + # 推荐实训 + def recommend_shixun shixun + shixun_id = ShixunTagRepertoire.where("tag_repertoire_id = #{shixun.tag_repertoires.first.present? ? shixun.tag_repertoires.first.try(:id) : 0} and shixun_id != #{shixun.id}").map(&:shixun_id) + shixuns = Shixun.select([:id, :name, :user_id, :status, :myshixuns_count, :trainee, :identifier]).where(:id => shixun_id, :status => 2, :hidden => 0).order("myshixuns_count desc").limit(3) + if shixuns.size < 3 + ids = shixuns.size == 0 ? "(-1)" : "(" + shixuns.map(&:id).join(',') + ")" + hot_shixuns = Shixun.select([:id, :name, :user_id, :status, :myshixuns_count, :trainee, :identifier]).where("status = 2 and hidden = 0 and id not in #{ids}").order("myshixuns_count desc").limit(3-shixuns.size) + return shixuns + hot_shixuns + else + return shixuns + end + end + + # 用户获取的技能标签 + def user_get_tags challenge_ids, user=User.current + tags = ChallengeTag.where(:challenge_id => user.games.where(:challenge_id => challenge_ids, :status => 2).pluck(:challenge_id)).pluck(:name).uniq + return tags + end + + # 所属路径 + def belongto_path shixun + Subject.where(:id => shixun.stage_shixuns.map(&:subject_id), :hidden => 0).limit(2) + end + + # 已授权老师加入示例课堂 + def join_ex_course user + course = Course.where(:id => 1309).first + if course + if course.members.where(:user_id => user.id).empty? + member = Member.new(:role_ids => [9], :user_id => user.id) + course.members << member + Tiding.create(:user_id => user.id, :trigger_user_id => 1, :container_id => course.id, :container_type => 'TeacherJoinCourse', :belong_container_id => course.id, :belong_container_type => "Course", :tiding_type => "System", :extra => "9") + end + end + end + +# 成员身份 + def member_zh_role member + role = "" + if member.roles.first + case member.roles.first.id + when 3 + role = "管理人员" + when 4 + role = "开发人员" + when 5 + role = "报告人员" + end + end + end + + def container_limit mirror_repositories + container = [] + mirror_repositories.each do |mr| + if mr.name.present? + container << {:image => mr.name, :cpuLimit => mr.cpu_limit, :memoryLimit => "#{mr.memory_limit}M", :type => mr.try(:main_type) == "1" ? "main" : "sub"} + end + end + return container.to_json + end + + # 实训作品列表的提交状态 + def list_work_status work, homework, member + if work.work_status == 0 + str = "未提交" + else + if work.compelete_status == 0 + setting_time = homework_group_setting homework, member.try(:course_group_id) + end_time = setting_time.end_time.present? ? setting_time.end_time : homework.end_time + if end_time > Time.now || (homework.allow_late && !homework.course.is_end) + str = "正在提交" + else + str = "延时提交" + end + else + if work.work_status == 1 + str = "按时提交" + else + str = "延时提交" + end + end + end + str + end + + # 试卷、问卷提交状态 + def ex_poll_work_status status + str = "" + case status + when 0 + str = "未提交" + when 1 + str = "按时提交" + when 2 + str = "延时提交" + end + str + end + + #传入分数,获取对应颜色 + def score_color score + if score + color = score >= 90 ? "color-red" : "color-green" + else + color = "color-grey" + end + color + end + + # 获取两断时间的日期差 + def time_between_days t1, t2 + Date.parse(t1.to_s) - Date.parse(t2.to_s) if t1.present? && t2.present? + end + + def update_valuate_time game_id, column + record = EvaluateRecord.where(:game_id => game_id).first + if record + consume_time = format("%.2f", (Time.now.to_f - record.created_at.to_f)).to_f + if column == "file_update" + record.update_attributes!(:file_update => consume_time) + elsif column == "pull" + record.update_attributes!(:consume_time => consume_time) + elsif column == "create_pod" + record.update_attributes!(:create_pod => consume_time) + elsif column == "pod_execute" + record.update_attributes!(:pod_execute => consume_time) + end + end + end + + # TPM查看权限 + # result一般为页面权限 + def shixun_view_allow shixun, result = nil + if User.current.manager_of_shixun?(shixun) + result ? false : true + else + if shixun.status == 0 || (shixun.use_scope == 1 && !shixun.schools.map(&:name).include?(User.current.school_name)) + result ? true : (render_403) + end + end + end + + # 判断TPM的代码是否被修改了 + # 判断依据是看tpm的最新提交记录和tpi数据库中存储的commit_id是否一致 + def repository_is_modified myshixun, shixun_gpid + g = Gitlab.client + myshixun_commit_id = myshixun.commit_id + if myshixun_commit_id.blank? + myshixun_commit_id = g.commits(myshixun.gpid).last.try(:id) + myshixun.update_column(:commit_id, myshixun_commit_id) + end + shixun_commit_id = g.commits(shixun_gpid).first.try(:id) + Rails.logger.warn("###############shixun_commit_id is #{shixun_commit_id}") + Rails.logger.warn("###############myshixun_commit_id is #{myshixun.commit_id}") + result = myshixun_commit_id != shixun_commit_id ? true :false + return result + end + + # 定义当前关卡是否有权开启下一关 + # :实训若发布了,必须通过当前关卡才能查看下一关 + # :未发布的实训,除了最后一关,其它的关卡都可以进入下一关 + def show_next_stage?(game, shixun_status) + if game.is_final_game? || ([2,3].include?(shixun_status.to_i) && game.try(:status) != 2) + false + else + true + end + end + + # 适用与已经用url_safe编码后,回调字符串形式 + def tran_base64_decode64 str + if str.blank? + str + else + s_size = str.size % 4 + if s_size != 0 + str += "=" * (4 - s_size) + end + Base64.decode64(str.tr("-_", "+/")).force_encoding("utf-8") + end + end + + def challenge_path path + cha_path = path.present? ? path.split(";") : [] + cha_path = cha_path.reject(&:blank?)[0].try(:strip) + cha_path + end + + def open_webssh + # 如果我webssh类型, 开启webssh + jenkins_shixuns = Redmine::Configuration['jenkins_shixuns'] + uri = URI("#{jenkins_shixuns}/jenkins-exec/webssh/getConnectInfo") + user_id = User.current.id + params = {userID:user_id} + res = uri_exec uri, params + return [host, port, username, password] + end + + # 中间层启动那种语言容器的类型 + # language 语言 exec_path 需要编译的文件路径 + def post_tomcat_language language, exec_path + if language == "Html" && !exec_path.blank? + case exec_path.split(".")[1].downcase + when "c" + "C" + when "cpp" + 'C++' + when "py" + 'Python2.7' + else + "Java" + end + elsif exec_path.blank? + "Java" + else + language + end + end + + def only_publish_game shixun, type + shixun_tomcat = Redmine::Configuration['shixun_tomcat'] + gameInfo = shixun.gameInfo + uri ="#{shixun_tomcat}/bridge/game/publishGame" + params = {:gameInfo => "#{gameInfo}"} + logger.info("%%%%%%%%%%%%params is #{params}") + res = uri_exec uri, params + if res && res['code'].to_i != 0 + raise("实训云平台繁忙(繁忙等级:90)") + end + end + + def publish_game_and_tpimodify myshixun, type + shixun_tomcat = Redmine::Configuration['shixun_tomcat'] + 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/resetTpiScript" + params = {:gameInfo => "#{gameInfo}"} + logger.info("%%%%%%%%%%%%params is #{params}") + res = uri_exec uri, params + if res && res['code'].to_i != 0 + raise("实训云平台繁忙(繁忙等级:98)") + end + end + + ## 若实训关卡位置,关卡数等信息发生变化则需要修改脚本内容 + def modify_shixun_script shixun, script + if script.present? + source_class_name = [] + challenge_program_name = [] + shixun.challenges.map(&:exec_path).each do |exec_path| + challenge_program_name << "\"#{exec_path}\"" + if shixun.mirror_name.try(:first) == "Java" + if exec_path.nil? || exec_path.split("src/")[1].nil? + source = "\"\"" + else + source = "\"#{exec_path.split("src/")[1].split(".java")[0]}\"" + end + source_class_name << source.gsub("/", ".") if source.present? + elsif shixun.mirror_name.try(:first) == "C#" + if exec_path.nil? || exec_path.split(".")[1].nil? + source = "\"\"" + else + source = "\"#{exec_path.split(".")[0]}.exe\"" + end + source_class_name << source if source.present? + end + end + script = if script.include?("sourceClassName") && script.include?("challengeProgramName") + script.gsub(/challengeProgramNames=\(.*\)/,"challengeProgramNames=\(#{challenge_program_name.reject(&:blank?).join(" ")}\)").gsub(/sourceClassNames=\(.*\)/, "sourceClassNames=\(#{source_class_name.reject(&:blank?).join(" ")}\)") + else + script.gsub(/challengeProgramNames=\(.*\)/,"challengeProgramNames=\(#{challenge_program_name.reject(&:blank?).join(" ")}\)").gsub(/sourceClassNames=\(.*\)/, "sourceClassNames=\(#{challenge_program_name.reject(&:blank?).join(" ")}\)") + end + end + return script + #shixun.update_column(:evaluate_script, script) + end + + # 若实训有更改,则修改已发不实训的标记为已更改 + # shixun_modifies表中1表示已更改,进入myshixun需要强制重置,0表示没有修改 + # type 0:表示已经是最新的了;1:表示已经有修改 + # res返回结果0表示正确,-1表示有异常 + def add_shixun_modify_status shixun, type + shixun_tomcat = Redmine::Configuration['shixun_tomcat'] + gameInfo = shixun.gameInfo + uri ="#{shixun_tomcat}/bridge/game/publishGame" + params = {:gameInfo => "#{gameInfo}"} + logger.info("%%%%%%%%%%%%params is #{params}") + res = uri_exec uri, params + if res && res['code'].to_i != 0 + raise("实训云平台繁忙(繁忙等级:90)") + end + end + + # 判断实训的路径、language是否更改,如果修改在TPI中需要重置脚本 + # 目前为止,container为challenge和game类型 + # 改工作必须在challenge或者game保存后执行 + # type 1:表示既需要提示又需要更新脚本的,0:表示仅仅需要提示 + def should_modify_myshixun_script shixun, type + if type == 1 + shixun.update_column(:reset_time, shixun.try(:updated_at)) + else + shixun.update_column(:modify_time, shixun.try(:updated_at)) + end + end + + def shixun_modify_status_publish shixun, type + shixun_tomcat = Redmine::Configuration['shixun_tomcat'] + # 更新测试集 + gameInfo = shixun.gameInfo + uri ="#{shixun_tomcat}/bridge/game/publishGame" + # 更新脚本 + tpiList =[] + myshixuns = shixun.myshixuns + if myshixuns.present? + myshixuns.each do |myshixun| + logger.info("tpiID is #{myshixun.id}") + tpiID = myshixun.id + instanceGitURL = gitlab_url myshixun + logger.info("instanceGitURL is #{instanceGitURL}") + tpiList << {:tpiID => tpiID, :instanceGitURL => instanceGitURL} + logger.info("###############{tpiList.to_json unless tpiList.blank?}") + end + end + tpiList = Base64.urlsafe_encode64(tpiList.to_json) unless tpiList.blank? + params = {:gameInfo => "#{gameInfo}", :tpiList => "#{tpiList}" } + logger.info("%%%%%%%%%%%%params is #{params}") + # end + res = uri_exec uri, params + if res && res['code'].to_i != 0 + raise("实训云平台繁忙(繁忙等级:90)") + end + end + + # 仅仅产生记录,用于已执行publish的方法 + # ShixunModify中status 1:表示有更改,开启实训的时候需要重置,0:表示不需要重置或已重置完成 + def shixun_modify_status_without_publish shixun, type + myshixuns = shixun.myshixuns + unless myshixuns.blank? + myshixuns.each do |myshixun| + shixun_modify = ShixunModify.where(:shixun_id => shixun.id, :myshixun_id => myshixun.id).first + if shixun_modify.nil? + ShixunModify.create!(:shixun_id => shixun.id, :myshixun_id => myshixun.id, :status => type) + else + shixun_modify.update_attributes!(:status => type) + end + end + end + end + + # 通关后,把最后一次成功的代码存到数据库 + # type 0 创始内容, 1 最新内容 + def game_passed_code game_id, path, myshixun_gpid, type + g = Gitlab.client + rev = rev.nil? ? "master" : rev + path = path.strip if path.present? + file_content = g.files(myshixun_gpid, path, rev).content + if file_content.blank? + # gitlab缺陷:forked完成,短暂时间内取不了内容的,所以做一个小轮询,间隔0.1秒 + # 超过2秒则失败,需通过页面刷新 + for i in 0..30 do + sleep(0.1) + file_content = g.files(myshixun_gpid, path, rev).content + unless file_content.blank? + break + end + end + end + unless file_content.present? + raise("获取文件代码异常") + end + file_content = tran_base64_decode64(file_content) + game_code = GameCode.where(:game_id => game_id, :path => path).first + if game_code.nil? + GameCode.create!(:game_id => game_id, :new_code => file_content, :path => path) + else + game_code.update_attributes!(:new_code => file_content) + end + end + + def game_code_init game_id, path + game_code = GameCode.where(:game_id => game_id, :path => path).first + GameCode.create(:game_id => game_id, :path => path) if game_code.blank? + end + + # 判断用户是否认证 + def check_authentication + # return true + # if params[:action] == "on_search" || params[:action] == "apply_trail" # 之所以这样处理是为了避开account页面ajax加载 + # return true + # end + Rails.logger.info("check_authentication start") + unless User.current.logged? + url = request.original_url + redirect_to signin_path(:back_url => url) + return + end +=begin + if User.current.created_on.strftime('%Y-%m-%d %H:%M:%S') > "2018-01-01 00:00:00" && User.current.phone.blank? + redirect_to change_or_bind_path(:type => "phone") + return + end +=end + user_e = UserExtensions.where(:user_id => User.current.id).first + if User.current.lastname.blank? || user_e.school_id.blank? || user_e.identity.blank? || User.current.mail.blank? + redirect_to user_info_path() + Rails.logger.info("check_authentication end") + return + elsif User.current.certification != 1 # 系统没有授权 + day_cer = UserDayCertification.where(:user_id => User.current.id).last + unless (Time.now.to_i - day_cer.try(:created_at).to_i) < 86400 + redirect_to my_account_path() + Rails.logger.info("check_authentication end") + return + end + end + end + + def match_specific_symbol(str) + str.gsub(" ", "").gsub(/\r\n$/, "").gsub("\r\n", "
    ").gsub(/\t/, "").html_safe + end + + # textarea 以/r/n开头时,回车效果会被替换,因此先把\r转换成\r 再添加一个\r(直接添加\r不行) + def match_specific_symbol1(str) + str.gsub(/\A\r/, "\r\r") + end + + # 积分表中建立记录行为,有过奖励则不重复奖励 + def reward_grade(user, container_id, container_type, score) + grade = Grade.where(:user_id => user.id, :container_id => container_id, :container_type => container_type).first + if grade.nil? + Grade.create!(:user_id => user.id, :container_id => container_id, :container_type => container_type, :score => score) + user.update_column(:grade, (score.to_i + user.grade.to_i)) + end + end + + def reward_experience(user, container_id, container_type, score) + experience = Experience.where(:user_id => user.id, :container_id => container_id, :container_type => container_type).first + if experience.nil? + Experience.create!(:user_id => user.id, :container_id => container_id, :container_type => container_type, :score => score) + user.update_column(:experience, (score.to_i + user.experience.to_i)) + end + end + + def shixun_name game_id + game = Game.where(:id => game_id).first + game.nil? ? "---" : game.challenge.shixun.name + end + + def grade_shixun_name shixun_id + shixun = Shixun.where(:id => shixun_id).first + shixun.nil? ? "---" : shixun.name + end + + def game_position game_id + game = Game.where(:id => game_id).first + game.nil? ? "---" : game.challenge.position + end + + def managements_navigation_bar_show menu_type, sub_type, grandchild_type={} + case menu_type + when 1 + case sub_type + when 1 then "统计总表" + when 2 then "数据变化报表" + end + when 2 + sub_type == 1 ? "课程列表" : (sub_type == 2? "课堂列表" : (sub_type == 3? "实训作业" : "项目列表")) + when 3 + case sub_type + when 1 + "实训列表" + when 2 + "实训配置列表" + when 3 + "已发布的实训" + when 4 + "已关闭的实训" + when 5 + "镜像管理" + when 6 + "学员实训列表" + when 7 + "镜像类别图片" + when 8 + "TPI实训列表" + when 9 + "TPI性能测试结果" + end + when 4 + case sub_type + when 1 + "实训课程列表" + when 2 + "实训课程配置" + when 3 + "已发布实训课程" + end + when 5 + case sub_type + when 1 + "竞赛列表" + end + when 6 + if sub_type == 1 + link_to('单位列表', departments_part_managements_path()) + "#{grandchild_type[:next_type] == 1 ? " > #{grandchild_type[:school].name}" : ""}" + elsif sub_type == 3 + "合作伙伴" + else + "单位部门列表" + end + when 7 + sub_type == 1 ? "用户列表" : (sub_type == 2 ? "试用授权列表" : "自动授权列表") + when 8 + sub_type == 1 ? "作业回复" : + (sub_type == 2 ? "实训反馈" : + (sub_type == 3 ? "讨论区" : "课堂讨论区") + ) + when 9 + sub_type == 1 ? "实训留言列表" : "" + when 10 + sub_type == 1 ? "实名认证" : + (sub_type == 2 ? "试用授权" : + (sub_type == 3 ? "部门审批" : + (sub_type == 4 ? "单位审批" : + (sub_type == 5 ? "实训发布" : + (sub_type == 6 ? "实训课程发布" : "职业认证") + ) + ) + ) + ) + when 11 + "工程认证+" + when 12 + sub_type == 1 ? "过关任务模板" : + (sub_type == 2 ? "实训简介模板" : + (sub_type == 3 ? "背景知识模板" : + (sub_type == 4 ? "通用评测模板" : + (sub_type == 5 ? "新课导语模板" : + (sub_type == 6 ? "实训评分设置" : + (sub_type == 7 ? "技术体系" : "升级通知") + ) + ) + ) + ) + ) + end + end + + + # codeMirror语言转换 + def language_switch language + case language + when "Java" + "text/x-java" + when "C" + "text/x-csrc" + when "C++" + "text/x-c++src" + when "Python" + "text/x-python" + when "Ruby" + "text/x-ruby" + end + end + + # 实训语言的种类 + def shixun_language + ["Java", "C", "C++", "Python2.7", "Python3.6", "MySQL/Java", "Html", "JFinal", "Docker", "Ethereum", "Dynamips", "MachineLearning", + "Verilog","Spark","MySQL/Python3.6","PHP","PHP/Web","Hadoop", "Golang","Android","Matlab","Shell", "Git", 'Perl6', 'Kotlin', 'Elixir', 'JavaScript', 'Ruby'] + end + + # 实训试用专业 + def shixun_major_option + content = [] + content << ["选择实训适用的专业", 0] + content << ["计算机科学与技术", 635] + content << ["软件工程", 636] + content << ["网络工程", 637] + content << ["信息安全", 638] + content << ["物联网工程", 639] + content << ["信息工程", 622] + content << ["通信工程", 619] + end + + # 实训面向学员 + def shixun_trainee + content = [] + content << ["初级学员", 1] + content << ["中级学员", 2] + content << ["高级学员", 3] + content << ["顶级学员", 4] + end + + # 班级设置排序中文 + def switch_to_chinese word + case word + when "boards" + result = "讨论区" + when "news" + result = "通知" + when "homework" + result = "作业" + when "exercises" + result = "试卷" + when "poll" + result = "问卷" + when "statistics" + result = "统计" + when "attachment" + result ="资源" + end + return result + end + + def allow_to_view_challenge challenge, shixun + # 判断对应关卡的game是否开启,如果开启则允许查看 + game_count = Game.where(:challenge_id => challenge, :user_id => User.current, :status => [0,1,2]).count + if game_count > 0 + return true + else + return false + end + end + + # 已通过的关卡数 + def had_passed_changllenge_count shixun, user + myshixun = Myshixun.where(:shixun_id => shixun.id, :user_id => user.id).first + if myshixun.nil? + 0 + elsif myshixun.games.select{|game| game.status == 2}.count == 0 + -1 + elsif myshixun.games.select{|game| game.status == 0}.count > 0 + [myshixun.games.select{|game| game.status == 2}.count + 1] + else + myshixun.games.select{|game| game.status == 2}.count + end + end + + # 判断TPM已通过的管卡数 + def had_passed_games_count shixun_id, user_id + #Game.find_by_sql("select count(*) as unpass_count from games where games.status=2 and user_id=#{user_id} and games.challenge_id in (select id from challenges where shixun_id=#{shixun_id})").first.try(:unpass_count) + Game.find_by_sql("SELECT count(*) cnt FROM `games` g join myshixuns m on m.id = g.myshixun_id where m.user_id = #{user_id} and m.shixun_id = #{shixun_id} and g.status = 2;").first.try(:cnt) + end + + # 用户实训评测状态 + def user_evaluate_status shixun, user + myshixun = shixun.myshixuns.where(:user_id => user.id).first + if myshixun.blank? + "--" + else + game_id = myshixun.games.map(&:id) + output = Output.where(:game_id => game_id).reorder("updated_at desc").first + if output.blank? + "--" + else + if output.try(:code) == -1 + time_from_now(output.updated_at).to_s + "评测失败" + else + time_from_now(output.updated_at).to_s + "评测成功" + end + end + end + end + + def student_work_performance score + case score + when (90..100) + '优秀' + when (70...90) + '良好' + when (60...70) + '及格' + when (0...60) + '不及格' + end + end + + # 已通过的关卡数 返回int类型(包含查看参考答案的) + def had_passed_changllenge_num myshixun + if myshixun.nil? + 0 + else + myshixun.games.select{|game| game.status == 2}.count + end + end + + # 已通过的关卡数 返回int类型(未查看参考答案) + def had_passed_no_ans_changllenge_num myshixun + if myshixun.nil? + 0 + else + myshixun.games.select{|game| game.status == 2 && game.final_score > 0}.count + end + end + + # TPI状态 :已通关、未通关、未开启 + def my_shixun_status shixun, user + status = "" + myshixun = Myshixun.where(:shixun_id => shixun.id, :user_id => user.id).first + if myshixun.nil? + status = "未开启" + else + status = myshixun.is_complete? ? "已通关" : "未通关" + end + status + end + + # 定义实训相关方法 + def sum_final_score + Game.find_by_sql("SELECT sum(final_score) as total_score FROM `games` where user_id=#{User.current.id}").first.try(:total_score) + end + + # 获取某个myshixun的得分 + def sum_myshixun_score myshixun_id + Game.find_by_sql("SELECT sum(final_score) as total_score FROM `games` where myshixun_id=#{myshixun_id}").first.try(:total_score) + end + + # myshixun 最高分 + def top_score shixun, position + Game.find_by_sql("SELECT max(final_score) as top_score FROM `games` g, `challenges` c where g.challenge_id = c.id and c.position=#{position} and g.myshixun_id in (SELECT id FROM `myshixuns` ms where ms.shixun_id=#{shixun.id})").first.try(:top_score) + end + + # 实训平均分 + def shixun_avg_score shixun, position + Game.find_by_sql("SELECT avg(g.final_score) as avg_score FROM `games` g, `challenges` c where g.challenge_id=c.id and c.position=#{position} and g.myshixun_id in (SELECT id FROM `myshixuns` ms where ms.shixun_id=#{shixun.id})").first.try(:avg_score) + end + + # 正在进行中任务 + def shixun_running shixun, position + Shixun.find_by_sql("SELECT count(*) as count FROM `myshixuns` ms, `games` g, `challenges` c where g.myshixun_id = ms.id and ms.shixun_id =#{shixun.id} and g.challenge_id=c.id and c.position=#{position} and g.status in ('0','1');").first.try(:count) + end + + # 已完成任务 + def shixun_done shixun, position + Shixun.find_by_sql("SELECT count(*) as count FROM `myshixuns` ms, `games` g, `challenges` c where g.myshixun_id = ms.id and ms.shixun_id =#{shixun.id} and g.challenge_id=c.id and c.position=#{position} and g.status=2;").first.try(:count) + end + + # 测评次数 + def shixun_exec_total_count shixun, position + Game.find_by_sql("SELECT * FROM `outputs` op, `games` g, `myshixuns` m where op.game_id = g.id and g.stage='#{position}' and m.parent_id = '#{shixun.id}';") + end + + # 平均耗时 + def game_avg_day created_at, updated_at + time = (updated_at - created_at).to_i + day = time / 86400 + end + + # 平均耗时 + def game_avg_hour created_at, updated_at + time = (updated_at - created_at).to_i + hour = time % (24*60*60) / (60*60) + end + + # 平均耗时 + def game_avg_min created_at, updated_at + time = (updated_at - created_at).to_i + min = time % (24*60*60) % (60*60) / 60 + end + + # 耗时:天、小时、分、秒 + # 小于1分钟则不显示 + def game_spend_time time + day = time / 86400 + hour = time % (24*60*60) / (60*60) + min = time % (24*60*60) % (60*60) / 60 + sec = time % (24*60*60) % (60*60) % 60 + if day < 1 + if hour < 1 + if min < 1 + if sec < 1 + time = "--" + else + time = "#{sec}秒" + end + else + time = "#{min}分钟 #{sec}秒" + end + else + time = "#{hour}小时 #{min}分钟 #{sec}秒" + end + else + time = "#{day}天 #{hour}小时 #{min}分钟 #{sec}秒" + end + return time + end + + # 耗时:天、小时、分 + # 小于1分钟则不显示 + def work_spend_time time + if time == 0 + time = "0小时" + else + day = time / 86400 + hour = time % (24*60*60) / (60*60) + min = (time % (24*60*60) % (60*60) / 60.0).ceil + if day < 1 + if hour < 1 + if min < 1 + time = "1分" + else + time = "#{min}分" + end + else + time = "#{hour}小时#{min}分" + end + else + time = "#{day}天#{hour}小时#{min}分" + end + end + return time + end + + # 耗时:小时、分、秒 00:00:00 + # 小于1秒钟则不显示 + def com_spend_time time + hour = time / (60*60) + min = time % (60*60) / 60 + sec = time % (60*60) % 60 + hour_str = "00" + min_str = "00" + sec_str = "00" + if hour >= 1 && hour < 10 + hour_str = "0#{hour}" + elsif hour >= 10 + hour_str = "#{hour}" + end + + if min >= 1 && min < 10 + min_str = "0#{min}" + elsif min >= 10 + min_str = "#{min}" + end + + if sec >= 1 && sec < 10 + sec_str = "0#{sec}" + elsif sec >= 10 + sec_str = "#{sec}" + end + + time = "#{hour_str} : #{min_str} : #{sec_str}" + return time + end + + def consume_time time + time.strftime('%Y/%m/%d %H:%M:%S') + end + + def avg_spend_time shixun_id, position + Game.find_by_sql("SELECT avg(g.end_time - g.open_time) as avg_time FROM `games` g, `challenges` c where c.id=g.challenge_id and g.status =2 and c.position = #{position} and g.myshixun_id in (SELECT id FROM `myshixuns` where shixun_id= #{shixun_id});").first.try(:avg_time).to_i + end + + # 已闯关 + def had_pass shixun_id, position + Game.find_by_sql("SELECT count(*) as count FROM `games` g, `challenges` c where c.id=g.challenge_id and g.status =2 and c.position =#{position} and g.myshixun_id in (SELECT id FROM `myshixuns` where shixun_id=#{shixun_id});").first.try(:count) + end + + # 单个game测评次数 + def avg_my_pass game + Output.where(:game_id => game).count + end + + def shixun_final_score myshixun + Game.find_by_sql("SELECT sum(final_score) as final_score FROM `games` where myshixun_id='#{myshixun.id}';").first.try(:final_score) + end + + # def user_blogs_path(resource,parameters={}) + # super + # end + # 复制一个任务 + def publish_games challenge, myshixun_id, index + game = Game.new + game.attributes = challenge.attributes.dup.except("id","shixun_id","user_id","visits") + game.myshixun_id = myshixun_id + game.user_id = User.current.id + game.stage = challenge.position + index == 0 ? game.status = 0 : game.status = 3 + challenge_samples = challenge.challenge_samples + test_sets = challenge.test_sets + if game.save + unless challenge_samples.blank? + challenge_samples.each do |cs| + ChallengeSample.create(:game_id => game.id, :input => cs.input, :output => cs.output, :challenge_id => -1) + end + end + unless test_sets.blank? + test_sets.each do |ts| + TestSet.create(:game_id => game.id, :input => ts.input, :output => ts.output, :challenge_id => -1) + end + end + end + end + + def git_repository_url project, type + if type == "Shixun" + rep_identify = Repository.where(:shixun_id => project.id, :type => "Repository::Gitlab").first.try(:identifier) + elsif type == "Myshixun" + rep_identify = Repository.where(:myshixun_id => project.id, :type => "Repository::Gitlab").first.try(:identifier) + else + rep_identify = Repository.where(:project_id => project.id, :type => "Repository::Gitlab").first.try(:identifier) + end + gitlab_address = Redmine::Configuration['gitlab_address'] + gitUrl = gitlab_address.to_s+"/"+project.owner.to_s+"/"+ rep_identify + "."+"git" + end + + def gitlab_url container + g = Gitlab.client + url = "#{Redmine::Configuration['gitlab_address_ip']}/#{g.project(container.try(:gpid)).try(:path_with_namespace)}.git" + end + + def gitlab_address_url container + g = Gitlab.client + url = "#{Redmine::Configuration['gitlab_address']}/#{g.project(container.try(:gpid)).try(:path_with_namespace)}.git" + end + + # paranet_gpid 为fork的源头 + # u_gid 为当前用户在gitlab中对应的用户id + def sync_gitlab_rep container, parent_gpid, u_gid + Rails.logger.info("# sync_gitlab_rep # parent_gpid is #{parent_gpid}, u_gid is #{u_gid}") + if container.class == Myshixun + gshixun = Gitlab.client.fork(parent_gpid, u_gid) + container.update_attribute(:gpid, gshixun.id) + end + return gshixun.try(:id) + end + + # def git_shixun_url shixun, login + # rep_identify = Repository.where(:shixun_id => shixun.id, :type => "Repository::Gitlab").first.try(:identifier) + # gitlab_address = Redmine::Configuration['gitlab_address'] + # gitUrl = gitlab_address.to_s+"/"+login+"/"+ rep_identify + "."+"git" + # end + + # def git_shixun_url_ip shixun, login + # rep_identify = Repository.where(:shixun_id => shixun.id, :type => "Repository::Gitlab").first.try(:identifier) + # gitlab_address = Redmine::Configuration['gitlab_address_ip'] + # gitUrl = gitlab_address.to_s+"/"+login+"/"+ rep_identify + "."+"git" + # end + + # def git_myshixun_url_ip myshixun, user_id + # g = Gitlab.client + # login = User.where(:id => user_id).first.try(:login) + # rep_identify = g.project(myshixun.gpid).try(:name) + # gitlab_address = Redmine::Configuration['gitlab_address_ip'] + # gitUrl = gitlab_address.to_s+"/"+login+"/"+ rep_identify + "."+"git" + # end + + # myshixun git url by domain + # def git_myshixun_url myshixun, user_id + # g = Gitlab.client + # login = User.where(:id => user_id).first.try(:login) + # rep_identify = g.project(myshixun.gpid).try(:name) + # gitlab_address = Redmine::Configuration['gitlab_address'] + # gitUrl = gitlab_address.to_s+"/"+login+"/"+ rep_identify + "."+"git" + # end + + def uri_exec uri, params + begin + Rails.logger.info("@parmas is #{params}, url is #{uri}") + uri = URI.parse(URI.encode(uri.strip)) + res = Net::HTTP.post_form(uri, params).body + res = JSON.parse(res) + rescue => e + Rails.logger.error("failed to post data to brige! #{e}") + raise("实训云平台繁忙(繁忙等级:84)") + end + end + + # type 为繁忙等级 + # status-> 501:check检查版本库是否有代码异常 + # status-> 502:实训评测异常;503实训版本库check异常 + def interface_post uri, params, status + begin + uri = URI.parse(URI.encode(uri.strip)) + res = Net::HTTP.post_form(uri, params).body + res = JSON.parse(res) + if (res && res['code'] != 0) + raise(status) + end + res + rescue Exception => e + Rails.logger.error("post failed! #{e}") + raise("实训云平台繁忙(繁忙等级:#{status})") + end + end + + def get_url_exec uri, options={} + begin + uri = URI.parse(URI.encode(uri.strip)) + res = Net::HTTP.get_response(uri).body + res = JSON.parse(res) + rescue => e + logger.error("get response failed ! #{e}") + raise("实训云平台繁忙(繁忙等级:84)") + end + end + + def uri_json_exec uri, params + Net::HTTP.start(uri.hostname, uri.port) {|http| + http.post(uri.path, params.to_json) + } + + http = Net::HTTP.new(uri.host, uri.port) + res = Net::HTTP.post(uri, params.to_json).body + res = JSON.parse(res) + end + + def last_reply_time container_id + message = Message.where(:root_id => container_id).order("created_on desc").first + time = message.created_on + return time + end + + def judge_Chinese_num str + cn_reg = /[\u4e00-\u9fa5]{1}/ + cn_number = str.scan(cn_reg).size + en_number = str.size - cn_number + size = 1.9* cn_number + en_number + end + + # homework_common状态 + # 0:挂起;1:提交中;2:匿评中;3:评阅中 + def new_homework_common_status status + case status + when 0 + "未发布" + when 1 + "提交中" + when 2 + "补交中" + when 3 + "匿评中" + when 4 + "申诉中" + when 5 + "评阅中" + when 6 + "已结束" + end + end + + # 作业不同状态的不同样式 + def homework_status_color status + style = "" + case status + when '未发布' + style = 'edu-filter-btn-no-late' + when '提交中', '评阅中', '匿评中', '交叉评阅中' + style = 'edu-filter-btn-orange' + when '已开启补交' + style = 'edu-filter-btn-green' + when '已截止', '未开启补交' + style = 'edu-filter-btn-red' + when '已结束' + style = 'edu-filter-btn-end' + when '申诉中' + style = 'edu-filter-btn-appeal' + end + end + + # 有分班权限的课堂 学生提交作品时发送的消息对象 + def tiding_teachers course, member + if course.teacher_course_groups.count > 0 + member_ids = course.teacher_course_groups.where(:course_group_id => member.try(:course_group_id)).pluck(:member_id) + + teachers = course.teachers.where("members.id not in (#{course.teacher_course_groups.pluck(:member_id).size > 0 ? course.teacher_course_groups.pluck(:member_id).join(',') : -1}) or + members.id in (#{member_ids.size > 0 ? member_ids.join(',') : -1})") + else + teachers = course.teachers + end + teachers + end + + # 分班管理的老师所看到的成员数 + def group_student_count course + member = @course.members.where(:user_id => User.current.id).first + if User.current.allowed_to?(:as_teacher, course) && member.present? && member.teacher_course_groups.count > 0 + student_count = course.members.where(:course_group_id => member.teacher_course_groups.pluck(:course_group_id)).select{|member| member.roles.to_s.include?("Student")}.count + else + student_count = course.student.count + end + student_count + end + + # 已提交作品 + def late_commit_work_status work, homework + if homework.allow_late + link_to "补交附件", student_work_path(work, :is_focus => 1), :class => 'edu-filter-btn edu-activity-orange ml15 fl mt5', :title => "可追加作品修订附件" + else + "未开启补交".html_safe + end + end + + # 未提交作品 + def un_commit_work_status project, homework + if homework.allow_late + if homework.homework_type == 3 && project.nil? && homework.homework_detail_group.base_on_project == 1 + link_to "补交作品", "javascript:void(0)", :class => 'edu-filter-btn edu-activity-orange ml15 fl mt5', :style => "cursor:not-allowed", :title => '请先关联项目再补交作品' + else + link_to "补交作品", new_student_work_url_without_domain(homework.id), :class => 'edu-filter-btn edu-activity-orange ml15 fl mt5' + end + else + "未开启补交".html_safe + end + end + + # 判断作业有多少人提交了 + # + def had_commit_studentwork_count homework_common + member = homework_common.course.members.where(:user_id => User.current.id).first + student_works = homework_common.student_works + if member.present? && member.teacher_course_groups.count > 0 + group_students = homework_common.course.members.where(:course_group_id => member.teacher_course_groups.pluck(:course_group_id)).map(&:user_id) + student_works = student_works.where(:user_id => group_students) + end + student_works.where("work_status !=?", 0).count + end + + # 实训作业的有效作品数 + def effective_shixun_work_count homework_common + count = 0 + shixun = homework_common.shixuns + if shixun + homework_common.student_works.where("work_status !=?", 0).each do |work| + myshixun = work.myshixun + count = count + (myshixun && myshixun.games.select{|game| game.status == 2}.size > 0 ? 1 : 0) + end + end + count + end + + # 实训作业的通关作品数 + def tongguan_shixun_work_count homework_common + count = 0 + shixun = homework_common.shixuns.first + if shixun + challenge_count = shixun.challenges.count + homework_common.student_works.where("work_status !=?", 0).each do |work| + myshixun = work.myshixun + if myshixun && myshixun.games.select{|game| game.status == 2}.size == challenge_count + count = count + 1 + end + end + end + count + end + + # 未提交作品数统计 + def had_uncommit_studentwork_count homework_common + member = homework_common.course.members.where(:user_id => User.current.id).first + student_works = homework_common.student_works + if member.present? && member.teacher_course_groups.count > 0 + group_students = homework_common.course.members.where(:course_group_id => member.teacher_course_groups.pluck(:course_group_id)).map(&:user_id) + student_works = student_works.where(:user_id => group_students) + end + student_works.where("work_status =?", 0).count + end + + # 未评阅 + def had_unevaluate_count homework_common + #count = StudentWorksScore.find_by_sql("SELECT count(distinct student_work_id) as count FROM student_works_scores sws, student_works sw, homework_commons hc where hc.id =#{homework_common.id} and sw.homework_common_id=hc.id and sw.is_delete = 0 and sws.student_work_id = sw.id and sws.user_id=#{User.current.id};").first.try(:count).to_i + member = homework_common.course.members.where(:user_id => User.current.id).first + student_works = homework_common.student_works + if member.present? && member.teacher_course_groups.count > 0 + group_students = homework_common.course.members.where(:course_group_id => member.teacher_course_groups.pluck(:course_group_id)).map(&:user_id) + student_works = student_works.where(:user_id => group_students) + end + has_comment = StudentWorksScore.where(:student_work_id => student_works.map(&:id), :reviewer_role => [1, 2]).group_by(&:student_work_id).count + student_count = student_works.count + return student_count - has_comment + end + + # 该阶段还有多长时间结束/距下一阶段还有多长时间 + def homework_curr_time homework_common + result = {} + status = "" + time = "" + if homework_common.course.try(:is_end) + status = "已结束" + time = format_date homework_common.course.end_date + else + ho_detail_manual = homework_common.homework_detail_manual + if ho_detail_manual + case ho_detail_manual.comment_status + when 0 + status = "未发布" + when 1 + if homework_common.end_time && homework_common.end_time >= Time.now + status = "提交中" + time = how_much_time(homework_common.end_time) + end + when 3 + if ho_detail_manual.evaluation_end && ho_detail_manual.evaluation_end > Time.now + status = "匿评中" + time = how_much_time(ho_detail_manual.evaluation_end) + end + when 4 + if ho_detail_manual.appeal_time && ho_detail_manual.appeal_time > Time.now + status = "申诉中" + time = how_much_time(ho_detail_manual.appeal_time) + end + when 5 + status = "评阅中" + when 6 + status = "评阅中" + end + end + end + result[:status] = status + result[:time] = time + result + end + + # 试卷:该阶段还有多长时间结束/距下一阶段还有多长时间 + def exercise_curr_time exercise + result = {} + status = "" + time = "" + case exercise.exercise_status + when 1 + status = "未发布" + when 2 + if exercise.end_time && exercise.end_time >= Time.now + status = "提交中" + time = how_much_time(exercise.end_time) + end + when 3 + status = "已截止" + time = format_time exercise.end_time + end + result[:status] = status + result[:time] = time + result + end + + # 问卷:该阶段还有多长时间结束/距下一阶段还有多长时间 + def poll_curr_time poll + result = {} + status = "" + time = "" + case poll.polls_status + when 1 + status = "未发布" + when 2 + if poll.end_time && poll.end_time >= Time.now + status = "提交中" + time = how_much_time(poll.end_time) + end + when 3 + status = "已截止" + time = format_time poll.end_time + end + result[:status] = status + result[:time] = time + result + end + + # 公共分页 + def paginator_list objs, objs_count, limit, is_remote + @is_remote = is_remote + @objs_count = objs.count + @obj_pages = Paginator.new @objs_count, limit, params['page'] || 1 + @offset ||= @obj_pages.offset + @objs = paginateHelper @attachments,25 + end + + # 判断当前用户能否对消息进行操作 + def allow_to_show applied_message + (User.current.id == applied_message.user_id && applied_message.status == 0) ? true : false + end + + # 获取竞赛的管理人员 + def contest_managers contest + contest.contest_members.select{|cm| cm.roles.to_s.include?("ContestManager")} + end + + # 获取竞赛的评委人员 + def contest_judges contest + contest.contest_members.select{|cm| cm.roles.to_s.include?("Judge")} + end + + # 获取竞赛的参赛人员 + def contest_contestants contest + contest.contest_members.select{|cm| cm.roles.to_s.include?("Contestant")} + end + + # 字符串加密 + def aes_encrypt(key, encrypted_string) + aes = OpenSSL::Cipher::Cipher.new("AES-128-ECB") + aes.encrypt + aes.key = key + txt = aes.update(encrypted_string) << aes.final + txt.unpack('H*')[0].upcase + end + + # 字符串解密 + def aes_dicrypt(key, dicrypted_string) + aes = OpenSSL::Cipher::Cipher.new("AES-128-ECB") + aes.decrypt + aes.key = key + aes.update([dicrypted_string].pack('H*')) << aes.final + end + # 获取多种类型的user用户名 + def user_message_username user + user.try(:show_name) + end + + # 超出1w后用k+形式显示 + def switch_integer_into_k number + number > 10000 ? (number.to_f / 1000).round.to_s + "k" : number + end + + # 判断某个课程是否包含仅对自己可见的作业 + def course_has_score_open_common_homework course + course.homework_commons.select{|hc| hc.score_open == 0}.count > 0 ? true : false + end + + def welcome_course_message_count course_id + board_id = Board.where(:course_id => course_id).first.try(:id) + message_count = Message.where(:board_id => board_id).count + return message_count + end + + # 可以查看到资源库的资源 + def welcome_course_file_count course + course.attachments.count + end + + # 超级管理员实训评分设置的横轴 + def shixun_quality_show quality + lower = quality.lower_limit + upper = quality.upper_limit + result = "#{quality.name}" + if lower.present? && upper.present? + result = if(lower > lower.round) + "#{result}(#{lower.round}," + else + "#{result}[#{lower.round}," + end + + result = if(upper >= upper.round) + "#{result}#{upper.round}]" + else + "#{result}#{upper.round})" + end + end + return result + end + + # 管理员实训评分中 "指标"与"标准"的对应 + def description_of_quality indicator, position + indicator.score_quality_descriptions.where(:position => position).first.try(:name) if indicator.present? + end + + # 获取目录下所有文件,返回一个文件名的数组 type是查看文件的类型image表示图片 + # type [[1, "图片"], [2, "apk/exe"], [3, "txt"], [4, "html"]] + def get_dir_filename path, type, game_id + answer_picture = [] + image = ["png", "jpg", "gif", "jpeg", "bmp", "pic"] + if File.directory? path + Dir.foreach(path) do |file| + if file !="." and file !=".." + extension = file.split(".")[1].try(:downcase) + if image.include?(extension) && type == 1 + answer_picture << file + @type = "image" + elsif extension == "html" && type == 4 + answer_picture << file + @type = "html" + elsif extension == "txt" && type == 3 + answer_picture << file + @contents = "" + f = File.open("#{path}/#{file}", "r") + # ... process the file + f.each_line do |line| + if line.include?("Your score") + game = Game.find(game_id) + max_query_index = game.query_index - 1 + a = line[11, line.length-1].try(:strip) + outputs = game.outputs.where(:query_index => max_query_index) + outputs.update_all(:text_scor => a) if outputs.present? + end + @contents += "#{line}" + end + f.close + @type = "txt" + end + end + end + end + return answer_picture + end + + # 隐藏项目以外的信息 + # return: true 显示,false 不显示 + def hidden_unproject_infos + hidden_info = Setting.find_by_name("hidden_non_project") + (hidden_info && hidden_info.value == "1") ? true : false + end + + # 获取当前用户的fork数量 + def get_fork_from_project forked_from_project_id + Project.find(forked_from_project_id) + end + + # 判断当前用户是否已经fork过当前项目 + # project: current_project + def has_forked_cur_project project + cur_user_projects = Project.where(:user_id => User.current.id) + if cur_user_projects.count == 0 + false + else + has_forked = cur_user_projects.select{|cur_user_project| cur_user_project.forked_from_project_id == project.id} + has_forked.length > 0 ? true : false + end + end + + # 判断当前用户是否已经实训过当前项目 + # project: current_project + def has_exec_cur_shixun shixun + Myshixun.where(:user_id => User.current.id, :shixun_id => shixun.id).count > 0 ? true : false + end + + # 用户必须登录;必须创建了关卡;有实践任务的必须提交了版本库代码 + def allow_shixun_exec shixun + g = Gitlab.client + result = User.current.logged? && shixun.challenges.count > 0 + if shixun.challenges.where(:st => 0).count > 0 + result = result && g.trees(shixun.gpid).count.to_i > 0 + end + result + end + + # 判断当前用户是否可以开始实战 + def link_to_shixun_exec myshixun, shixun, str + is_modify = ShixunModify.where(:myshixun_id => myshixun.try(:id), :shixun_id => shixun.try(:id), :status => 1).first.blank? + if User.current.mail.blank? + link_to str, "javascript:void(0);", :onclick => "notice_box_redirect('#{security_settings_path}', '开启实训,请先绑定邮箱')", :class => "fr shixun-task-btn task-btn-orange mr15", :target => "_blank" + else + if is_modify || myshixun.blank? + link_to str, shixun_exec_shixun_path(shixun), :class => "fr shixun-task-btn task-btn-orange mr15", :target => "_blank" + else + link_to str, "javascript:void(0);", :onclick => "sure_box_redirect('#{myshixun_reset_myshixun_path(myshixun)}', '实训已经更新啦,系统正在为您重置')", :class => "fr shixun-task-btn task-btn-orange mr15" + end + end + end + + # 通过系统外部邮箱查找用户,如果用户不存在则用邮箱替换 + def get_user_by_mail mail + user = User.find_by_mail(mail) + user.nil? ? User.find(2) : user + end + + # 通过登录名查找用户,能查到返回用户姓名,否则返回登录名 + def link_to_user_login login, css_class + user = User.find_by_login(login) + user = user.nil? ? login : user + if user.is_a?(User) + name = user.show_name + link_to name, {:controller=> 'users', :action => 'show', id: user.id}, :class => css_class, :target => "_blank" + else + "#{h(user.to_s)}".html_safe + end + end + + def link_to_user_mail(mail, css_class) + user = User.find_by_mail(mail) + user = user.nil? ? mail : user + if user.is_a?(User) + name = user.show_name + link_to name, {:controller=> 'users', :action => 'show', id: user.id}, :class => css_class, :target => "_blank" + else + "#{h(user.to_s)}".html_safe + end + end + + # 通过系统外部用户名查找用户,如果用户不存在则用邮箱替换 + def get_user_by_login_and login + user = User.find_by_login(login) + (user.nil? || login == "root") ? User.find(2) : user + end + + # 登录名来自外部系统 + # 通过登录名查找用户,如果用户存在则显示用户姓名,否则显示登录名 + def get_user_by_login login + user = User.find_by_login(login) + user.nil? ? login : user.show_name + end + + # 重置user_path,目的是将id转换成用户名 + def user_path(resource, parameters = {}) + if Fixnum === resource + resource = User.find(resource) + end + super + end + + # 重置user_path,目的是将id转换成用户名 + # def shixun_path(resource, parameters = {}) + # if Fixnum === resource + # resource = Shixun.find(resource) + # end + # super + # end + + # 历史数据(老版本库数据)处理完则可以修改该放放 + def get_rep_identifier_by_project project + identifier = Repository.where(:project_id => project.id, :type => "Repository::Gitlab").first.try(:identifier) + result = identifier.nil? ? Repository.where(:project_id => project.id).first.try(:identifier) : identifier + result + end + + # 项目版本库导出Excel功能 + def export_rep_xls(gpid, options = {}) + g = Gitlab.client + cycle = params[:cycle] + rev = params[:rev] + if cycle == "week" + statics = g.rep_stats_week(gpid, :rev => rev) + elsif cycle == "month" + statics = g.rep_stats_month(gpid, :rev => rev) + end + xls_report = StringIO.new + book = Spreadsheet::Workbook.new + sheet1 = book.create_worksheet :name => l(:project_module_repository) + blue = Spreadsheet::Format.new :color => :blue, :weight => :bold, :size => 10 + sheet1.row(0).default_format = blue + sheet1.row(0).concat([l(:rep_branch),l(:rep_author),l(:rep_changeset),l(:rep_code_add),l(:rep_code_delete),l(:rep_code_modified),l(:rep_sode_time),l(:rep_sode_cycle),l(:rep_author_mail)]) + count_row = 1 + statics.each do |static| + user = User.where(:mail => static.email).first + sheet1[count_row,0] = rev + sheet1[count_row,1] = user.nil? ? static.uname : user.show_name + sheet1[count_row,2] = static.commits_num + sheet1[count_row,3] = static.add + sheet1[count_row,4] = static.del + sheet1[count_row,5] = static.changes + sheet1[count_row,6] = Time.now.strftime('%Y-%m-%d %H:%M:%S') + sheet1[count_row,7] = cycle == "week" ? "最近1周" : "最近一月" + sheet1[count_row,8] = static.email + count_row += 1 + end + book.write xls_report + xls_report.string + end + + # 项目issue列表导出Excel功能 + def issue_list_xls issues + xls_report = StringIO.new + book = Spreadsheet::Workbook.new + sheet1 = book.create_worksheet :name => "issues" + blue = Spreadsheet::Format.new :color => :blue, :weight => :bold, :size => 10 + sheet1.row(0).default_format = blue + sheet1.row(0).concat([l(:issue_xls_id),l(:issue_xls_tracker_id),l(:issue_xls_title),l(:issue_xls_description),l(:issue_xls_status),l(:issue_xls_assign),l(:issue_xls_priority),l(:issue_xls_author),l(:issue_xls_created_at),l(:milestone),l(:issue_xls_start),l(:issue_xls_due),l(:issue_xls_ratio)]) + count_row = 1 + issues.each do |issue| + sheet1[count_row,0] = issue.id + sheet1[count_row,1] = issue_tracker_change(issue.tracker_id) + sheet1[count_row,2] = issue.subject + sheet1[count_row,3] = (issue.description.gsub(/<\/?.*?>/,"")).html_safe + sheet1[count_row,4] = issue_status_change(issue.status_id) + sheet1[count_row,5] = issue.assigned_to.try(:show_name) + sheet1[count_row,6] = issue_priority_change(issue.priority_id) + sheet1[count_row,7] = issue.author.show_name + sheet1[count_row,8] = issue.created_on.nil? ? issue.created_on : issue.created_on.strftime('%Y-%m-%d %H:%M:%S') + sheet1[count_row,9] = issue.fixed_version.try(:name) + sheet1[count_row,10] = issue.start_date.nil? ? issue.start_date : issue.start_date.strftime('%Y-%m-%d') + sheet1[count_row,11] = issue.due_date.nil? ? issue.due_date : issue.due_date.strftime('%Y-%m-%d') + sheet1[count_row,12] = issue_ratio_change(issue.done_ratio, issue.status_id) + count_row += 1 + end + book.write xls_report + xls_report.string + end + + # 用户资料是否完善 + def user_data_complete user + user_extension = UserExtensions.where(:user_id => user.id).first + data = true + if user_extension.gender.nil? || user_extension.school_id.nil? || user.lastname.blank? || (user_extension.identity == 3 && user_extension.school_id.nil?) + data = false + end + return data + end + + # 获取用户单位 + # 优先获取高校信息,如果改信息不存在则获取occupation + def get_occupation_from_user user + School.where("id=?",user.user_extensions.school_id).first.try(:name).nil? ? user.user_extensions.try(:occupation) : School.where("id=?",user.user_extensions.school_id).first.try(:name) + end + + def update_visiti_count container + container.update_column(:visits, container.visits + 1) + end + + def if_hidden_subdomain field + domains = field.sub_domains.select{|domain| domain.hide.to_i == 0} + result = domains.length > 0 ? true : false + return result + end + + # 判断某个资源是否可以申请 + def attach_show_allow attach_id + attachment = Attachment.find(attach_id) + case attachment.container_type + when "Project" + User.current.member_of?(attachment.container) ? true : false + when "Course" + User.current.member_of_course?(attachment.container) ? true : false + when "OrgSubfield" + User.current.member_of_org?(attachment.container.organization) ? true : false + when "Principal" + User.current.id == attachment.author_id ? true : false + end + end + + # 判断某个私有资源是否可以发送下载权限 + # 结果为true不能下载,false可以下载 + def private_attachment_allow attachment_id + attach = Attachment.find(attachment_id) + # 条件取否,result结果为true则不能下载 + result = attach.is_public == 0 && attach.author != User.current && !attach.get_apply_resource_status(attach.id, User.current.id) && !attach_show_allow(attach) + end + + # Time 2015-03-24 15:27:29 + # Author lizanle + # Description 从硬盘上删除对应的资源文件 + def delete_kindeditor_assets_from_disk owner_id,owner_type + assets = Kindeditor::Asset.where(["owner_id = ? and owner_type = ?",owner_id,owner_type]) + if !assets.nil? && !assets.blank? + assets.all.each do |asset| + next if asset.nil? + filepath = File.join(Rails.root,"public","files","uploads", + asset[:created_at].to_s.gsub("+0800","").to_datetime.strftime("%Y%m").to_s, + asset[:asset].to_s) + File.delete(filepath) if File.exist?filepath + end + end + end + + def link_to_user_version(version, options = {}) + return '' unless version && version.is_a?(Version) + link_to_if version.visible?, format_version_name(version), { :controller => 'versions', :action => 'show', :id => version }, :class => "linkBlue" + end + + # 判断课程是否为精品课程 + def is_excellent_course course + (course.is_excellent? or course.excellent_option?) ? true : false + end + + # 判断课程对成员是否可见 + def visible_course?(course) + (course.is_delete? or (!course.is_public? && !User.current.member_of_course?(course))) ? false : true + end + + # 获取项目/课程总分 + # 发布缺陷 4分 回复缺陷 1分 提交一次 4分 讨论帖子 2分 回复帖子 1分 发布新闻 1分 + def static_project_score obj + score = obj.issue_num * 4 + obj.issue_journal_num + (obj.changeset_num||0) * 4 + obj.board_num * 2 + obj.board_message_num + obj.attach_num * 5 + end + + # 获取组织成员中文名字 + def get_org_member_role_name member + unless member.roles[0].nil? + case member.roles[0].name + when 'orgManager' + '管理人员' + when 'orgMember' + '组织成员' + end + end + end + + # 判断组织左侧展开或者隐藏 + def is_hide_org_left obj + if obj.nil? + return true + else + if obj.hide == 0 + return true + else + return false + end + end + end + + # Time 2015-03-24 16:38:05 + # Author lizanle + # Description after save后需要进行资源记录的更新 + # owner_type = 1 对应的是 memo + # owner_type = 2 对应的是forum + # owner_type = 3 对应的是message + # owner_type = 4 对应的是news + # owner_type = 5 对应的是comment + def update_kindeditor_assets_owner ids,owner_id,owner_type + ids.each do |id| + asset = Kindeditor::Asset.find(id.to_i) + asset.owner_id = owner_id + asset.owner_type = owner_type + asset.save + end + end + + # 更新课程活跃度得分 + def course_member_score(course_id,user_id,type) + course_contributor_score = CourseContributorScore.where("course_id =? and user_id =?", course_id, user_id).first + case type + when "HomeworkCommon" + if course_contributor_score.nil? + CourseContributorScore.create(:course_id => course_id, :user_id => user_id, :homework_journal_num => 1) + else + score = course_contributor_score.homework_journal_num.to_i + 1 + course_contributor_score.update_column(:homework_journal_num, score) + end + # 课程留言 + when "Course" + if course_contributor_score.nil? + CourseContributorScore.create(:course_id => course_id, :user_id => user_id, :journal_num => 1) + else + score = course_contributor_score.journal_num.to_i + 1 + course_contributor_score.update_column(:journal_num, score) + end + when "Message" + if course_contributor_score.nil? + CourseContributorScore.create(:course_id => course_id, :user_id => user_id, :message_num => 1) + else + score = course_contributor_score.message_num.to_i + 1 + course_contributor_score.update_column(:message_num, score) + end + when "MessageReply" + if course_contributor_score.nil? + CourseContributorScore.create(:course_id => course_id, :user_id => user_id, :message_reply_num => 1) + else + score = course_contributor_score.message_reply_num.to_i + 1 + course_contributor_score.update_column(:message_reply_num, score) + end + when "NewReply" + if course_contributor_score.nil? + CourseContributorScore.create(:course_id => course_id, :user_id => user_id, :news_reply_num => 1) + else + score = course_contributor_score.news_reply_num.to_i + 1 + course_contributor_score.update_column(:news_reply_num, score) + end + when "News" + if course_contributor_score.nil? + CourseContributorScore.create(:course_id => course_id, :user_id => user_id, :news_num => 1) + else + score = course_contributor_score.news_num.to_i + 1 + course_contributor_score.update_column(:news_num, score) + end + when "Attachment" + if course_contributor_score.nil? + CourseContributorScore.create(:course_id => course_id, :user_id => user_id, :resource_num => 1) + else + score = course_contributor_score.resource_num.to_i + 1 + course_contributor_score.update_column(:resource_num, score) + end + end + end + + # 删除某条记录相应减少课程统计数 + def down_course_score_num (course_id,user_id,type) + course_contributor_score = CourseContributorScore.where("course_id =? and user_id =?", course_id, user_id).first + case type + when "HomeworkCommon" + unless course_contributor_score.nil? + score = course_contributor_score.homework_journal_num.to_i - 1 + course_contributor_score.update_column(:homework_journal_num, score < 0 ? 0 : score) + end + # 课程留言 + when "Course" + unless course_contributor_score.nil? + score = course_contributor_score.journal_num.to_i - 1 + course_contributor_score.update_column(:journal_num, score < 0 ? 0 : score) + end + when "Message" + unless course_contributor_score.nil? + score = course_contributor_score.message_num.to_i - 1 + course_contributor_score.update_column(:message_num, score < 0 ? 0 : score) + end + when "MessageReply" + unless course_contributor_score.nil? + score = course_contributor_score.message_reply_num.to_i - 1 + course_contributor_score.update_column(:message_reply_num, score < 0 ? 0 : score) + end + when "NewReply" + unless course_contributor_score.nil? + score = course_contributor_score.news_reply_num.to_i - 1 + course_contributor_score.update_column(:news_reply_num, score < 0 ? 0 : score) + end + when "News" + unless course_contributor_score.nil? + score = course_contributor_score.news_num.to_i - 1 + course_contributor_score.update_column(:news_num, score < 0 ? 0 : score) + end + when "Attachment" + unless course_contributor_score.nil? + score = course_contributor_score.resource_num.to_i - 1 + course_contributor_score.update_column(:resource_num, score < 0 ? 0 : score) + end + end + end + + # Added by young + # Define the course menu's link class + # 不是数组的转化成数组,然后判断当前menu_item是否在给定的列表 + # REVIEW: 目测menu的机制,貌似不是很需要转换,再说 + def link_class(label) + labels = label.is_a?(Array) ? label : ([] << label) + #a = current_menu_item + labels.include?(current_menu_item) ? 'selected' : '' + + end + #Ended by young + # Return true if user is authorized for controller/action, otherwise false + def authorize_for(controller, action) + User.current.allowed_to?({:controller => controller, :action => action}, @project) + end + + # add by nwb + def authorize_for_course(controller, action) + User.current.allowed_to?({:controller => controller, :action => action}, @course) + end + + def authorize_for_contest(controller, action) + User.current.allowed_to?({:controller => controller, :action => action}, @contest) + end + + # Display a link if user is authorized + # + # @param [String] name Anchor text (passed to link_to) + # @param [Hash] options Hash params. This will checked by authorize_for to see if the user is authorized + # @param [optional, Hash] html_options Options passed to link_to + # @param [optional, Hash] parameters_for_method_reference Extra parameters for link_to + def link_to_if_authorized(name, options = {}, html_options = nil, *parameters_for_method_reference) + link_to(name, options, html_options, *parameters_for_method_reference) if authorize_for(options[:controller] || params[:controller], options[:action]) + end + + def link_to_if_authorized_course(name, options = {}, html_options = nil, *parameters_for_method_reference) + link_to(name, options, html_options, *parameters_for_method_reference) if authorize_for_course(options[:controller] || params[:controller], options[:action]) + end + + def link_to_if_authorized_contest(name, options = {}, html_options = nil, *parameters_for_method_reference) + link_to(name, options, html_options, *parameters_for_method_reference) if authorize_for_contest(options[:controller] || params[:controller], options[:action]) + end + # Displays a link to user's account page if active + def link_to_user(user, canShowRealName = false, options={}) + if user.is_a?(User) + if canShowRealName + name = h(user.realname(options[:format])) + else + name = h(user.name(options[:format])) + end + + #if user.active? || (User.current.admin? && user.logged?) + # link_to name, {:controller=> 'users', :action => 'show', id: user.id, host: Setting.host_user}, :class => user.css_classes + #else + # name + #end + link_to name, {:controller=> 'users', :action => 'show', id: user.id, host: Setting.host_user}, :class => user.css_classes + else + h(user.to_s) + end + end + + def link_to_isuue_user(user, options={}) + if user.is_a?(User) + if options[:format] + name = h(user.name(options[:format])) + else + name = h(user.show_name) + end + link_to name, {:controller=> 'users', :action => 'show', id: user.id, host: Setting.host_user}, :class => "pro_info_p" + else + h(user.to_s) + end + end + + def link_to_settings_user(user, options={}) + if user.is_a?(User) + name = h(user.name(options[:format])) + link_to name, {:controller=> 'users', :action => 'show', id: user.id, host: Setting.host_user}, :class => "w90 c_orange fl" + else + h(user.to_s) + end + end + + #重载上面方法,增加样式显示 + def link_to_user_header user,canShowRealName=false,options={} + if user.is_a?(User) + if canShowRealName + name = user.show_name + name = user.login if name == "" + else + name = user.login + end + link_to name, {:controller=> 'users', :action => 'show', id: user.id, host: Setting.host_user}, :class => options[:class] + else + h(user.to_s) + end + end + + # Displays a link to +issue+ with its subject. + # Examples: + # + # link_to_issue(issue) # => Defect #6: This is the subject + # link_to_issue(issue, :truncate => 6) # => Defect #6: This i... + # link_to_issue(issue, :subject => false) # => Defect #6 + # link_to_issue(issue, :project => true) # => Foo - Defect #6 + # link_to_issue(issue, :subject => false, :tracker => false) # => #6 + # + def link_to_issue(issue, options={}) + title = nil + subject = nil + text = options[:tracker] == false ? "##{issue.id}" : "#{issue.tracker} ##{issue.id}" + if options[:subject] == false + title = truncate(issue.subject, :length => 60) + else + subject = issue.subject + if options[:truncate] + subject = truncate(subject, :length => options[:truncate]) + end + end + s = link_to text, issue_path(issue), :class => issue.css_classes, :title => title + s << h(": #{subject}") if subject + s = h("#{issue.project} - ") + s if options[:project] + s + end + + def link_to_issue_version(issue, options={}) + title = nil + subject = nil + text = options[:tracker] == false ? "##{issue.id}" : "#{issue.tracker} ##{issue.id}" + if options[:subject] == false + title = truncate(issue.subject, :length => 60) + else + subject = issue.subject + if options[:truncate] + subject = truncate(subject, :length => 60) + end + end + # status_id:3、已解决 5、已关闭 + if issue.status_id == 3 + s = link_to text, issue_path(issue), :class => "text_line_s fl", :title => title + elsif issue.status_id == 5 + s = link_to text, issue_path(issue), :class => "text_line_s del_line fl", :title => title + else + s = link_to text, issue_path(issue), :class => "c_blue fl", :title => title + end + s << h("".html_safe) if subject + s = h("#{issue.project} - ") + s if options[:project] + s + end + + # Generates a link to an attachment. + # Options: + # * :text - Link text (default to attachment filename) + # * :download - Force download (default: false) + def link_to_short_attachment(attachment, options={}) + length = options[:length] ? options[:length]:23 + text = h(truncate(options.delete(:text) || attachment.filename, length: length, omission: '...')) + route_method = options.delete(:download) ? :download_named_attachment_url_without_domain : :named_attachment_url_without_domain + html_options = options.slice!(:only_path) + url = send(route_method, attachment, attachment.filename, options) + link_to text, url, html_options + end + + # Generates a link to an attachment. + # Options: + # * :text - Link text (default to attachment filename) + # * :download - Force download (default: false) + def link_to_attachment(attachment, options={}) + token = options[:token] if options[:token] + text = options.delete(:text) || attachment.filename + route_method = options.delete(:download) ? :download_named_attachment_path : :named_attachment_path + html_options = options.slice!(:only_path) + url = send(route_method, attachment, attachment.filename, options) + url << "?token=#{token}" unless token.nil? + link_to text, url, html_options + end + + def link_to_attachment_img(attachment, options={}) + text = options.delete(:text) || attachment.filename + route_method = options.delete(:download) ? :download_named_attachment_path : :named_attachment_path + html_options = options.slice!(:only_path) + url = send(route_method, attachment, attachment.filename, options) + image_tag url, html_options + end + + # Generates a link to a SCM revision + # Options: + # * :text - Link text (default to the formatted revision) + def link_to_revision(revision, repository, options={}) + if repository.is_a?(Project) + repository = repository.repository + end + text = options.delete(:text) || format_revision(revision) + rev = revision.respond_to?(:identifier) ? revision.identifier : revision + link_to( + h(text), + {:controller => 'repositories', :action => 'revision', :id => repository.project, :repository_id => repository.identifier_param, :rev => rev}, + :title => l(:label_revision_id, format_revision(revision)) + ) + end + + # Generates a link to a message + def link_to_message(message, options={}, html_options = nil) + link_to( + truncate(message.subject, :length => 60), + board_message_path(message.board_id, message.parent_id || message.id, { + :r => (message.parent_id && message.id), + :anchor => (message.parent_id ? "message-#{message.id}" : nil) + }.merge(options)), + html_options + ) + end + + # Generates a link to a project if active + # Examples: + # + # link_to_project(project) # => link to the specified project overview + # link_to_project(project, {:only_path => false}, :class => "project") # => 3rd arg adds html options + # link_to_project(project, {}, :class => "project") # => html options with default url (project overview) + # + def link_to_project(project, options={}, html_options = nil) + if project.archived? + h(project.name) + elsif options.key?(:action) + ActiveSupport::Deprecation.warn "#link_to_project with :action option is deprecated and will be removed in Redmine 3.0." + url = {:controller => 'projects', :action => 'show', :id => project}.merge(options) + link_to project.name, url, html_options + else + link_to project.name, project_path(project, options), html_options + end + end + + def link_to_course(course, options={}, html_options = nil) + if course.archived? + h(course.name) + elsif options.key?(:action) + ActiveSupport::Deprecation.warn "#link_to_course with :action option is deprecated and will be removed in Redmine 3.0." + url = {:controller => 'courses', :action => 'show', :id => project}.merge(options) + link_to course.name, url, html_options + else + link_to course.name, course_path(course, options), html_options + end + end + + # Generates a link to a project settings if active + def link_to_project_settings(project, options={}, html_options=nil) + if project.active? + link_to project.name, settings_project_path(project, options), html_options + elsif project.archived? + h(project.name) + else + link_to project.name, project_path(project, options), html_options + end + end + + def wiki_page_path(page, options={}) + url_for({:controller => 'wiki', :action => 'show', :project_id => page.project, :id => page.title}.merge(options)) + end + + def thumbnail_tag(attachment) + link_to image_tag(thumbnail_path(attachment)), + named_attachment_path(attachment, attachment.filename), + :title => attachment.filename + end + + def thumbnail_issue_tag(attachment) + imagesize = attachment.thumbnail(:size => "200*200") + imagepath = named_attachment_path(attachment, attachment.filename) + if imagesize + link_to image_tag(thumbnail_path(attachment), height: '73', width: '100', class: 'issue_attachment_picture'), + imagepath, + :title => attachment.filename + + else + link_to image_tag(imagepath , height: '73', width: '100', class: 'issue_attachment_picture'), + imagepath, + :title => attachment.filename + end + end + + def thumbnail_challenge_tag(attachment) + imagepath = named_attachment_path(attachment, attachment.filename) + image_tag(imagepath) + end + + # 图片缩略图链接 + def thumbnail_small_tag(attachment) + imagesize = attachment.thumbnail(:size => "200*200") + imagepath = named_attachment_path(attachment, attachment.filename) + if imagesize + link_to image_tag(imagesize), + imagepath, + :title => attachment.filename + else + link_to image_tag(imagepath , height: '200', width: '250'), + imagepath, + :title => attachment.filename + end + end + + def toggle_link(name, id, options={}) + onclick = "$('##{id}').slideToggle(); " + onclick << (options[:focus] ? "$('##{options[:focus]}').focus(); " : "this.blur(); ") + onclick << "return false;" + link_to(name, "javascript:void(0)", :onclick => onclick,:class => options[:class]) + end + + def image_to_function(name, function, html_options = {}) + html_options.symbolize_keys! + tag(:input, html_options.merge({ + :type => "image", :src => image_path(name), + :onclick => (html_options[:onclick] ? "#{html_options[:onclick]}; " : "") + "#{function};" + })) + end + + def format_activity_title(text) + h(truncate_single_line(text, :length => 100)) + end + + def format_activity_day(date) + date == User.current.today ? l(:label_today).titleize : format_date(date) + end + + def format_activity_description(text) + h(truncate(text.to_s, :length => 120).gsub(%r{[\r\n]*<(pre|code)>.*$}m, '...')).gsub(/[\r\n]+/, "
    ").html_safe + #h(truncate(text.to_s, :length => 120).gsub(/<\/?.*?>/,"")).html_safe + end + + def format_version_name(version) + if version.project == @project + h(truncate(version.name,:length=>20)) + else + h("#{version.project} - #{truncate(version.name,:length=>20)}") + end + end + + def due_date_distance_in_words(date) + if date + l((date < Date.today ? :label_roadmap_overdue : :label_roadmap_due_in), distance_of_date_in_words(Date.today, date)) + end + end + + # Renders a tree of projects as a nested set of unordered lists + # The given collection may be a subset of the whole project tree + # (eg. some intermediate nodes are private and can not be seen) + #Modified by nie. + def render_project_nested_lists(projects) + s = '' + if projects.any? + ancestors = [] + original_project = @project + #modified by nie + projects.each do |project| + # set the project environment to please macros. + @project = project + if (ancestors.empty? || project.is_descendant_of?(ancestors.last)) +# s << "
      \n" + s << "
        \n" + else + ancestors.pop + s << "" + while (ancestors.any? && !project.is_descendant_of?(ancestors.last)) + ancestors.pop + s << "
      \n" + end + end + classes = (ancestors.empty? ? 'root' : 'child') + s << "
    • " + if project.try(:project_type) == Project::ProjectType_project + s << h(block_given? ? yield(project) : project.name) + else + end + + if project.try(:project_type) == Project::ProjectType_project + unless User.current.member_of?(@project) + s << "" + s << watcher_link(@project, User.current)#, ['whiteButton']) + s << "" + end + s << (render :partial => 'projects/tracker_project', :locals => {:project => project}).to_s + else + s << (render :partial => 'projects/course', :locals => {:project => project}).to_s + end + s << "
      \n" + ancestors << project + end + s << ("
    \n" * ancestors.size) + @project = original_project + end + s.html_safe + end + + def render_course_nested_lists(courses) + s = '' + if courses.any? + ancestors = [] + original_course = @course + #modified by nie + courses.each do |course| + # set the project environment to please macros. + @course = course + if (ancestors.empty? )#|| course.is_descendant_of?(ancestors.last)) + s << "
      \n" + else + ancestors.pop + s << "" + while (ancestors.any? )#&& !course.is_descendant_of?(ancestors.last)) + ancestors.pop + s << "
    \n" + end + end + classes = (ancestors.empty? ? 'root' : 'child') + s << "
  • " + + s << (render :partial => 'courses/course', :locals => {:course => course}).to_s + s << "
    \n" + ancestors << course + end + s << ("
  • \n" * ancestors.size) + @course = original_course + end + s.html_safe + end + + + #added by young + def render_project_nested_lists_new(projects) + s = '' + if projects.any? + ancestors = [] + original_project = @project + projects.sort_by(&:lft).each do |project| + # set the project environment to please macros. + @project = project + if (ancestors.empty? || project.is_descendant_of?(ancestors.last)) +# s << "
      \n" + s << "
        \n" + else + ancestors.pop + s << "" + while (ancestors.any? && !project.is_descendant_of?(ancestors.last)) + ancestors.pop + s << "
      \n" + end + end + classes = (ancestors.empty? ? 'root' : 'child') + s << h(block_given? ? yield(project) : project.name) + ancestors << project + end + s << ("
    \n" * ancestors.size) + @project = original_project + end + s.html_safe + end + #end + def render_page_hierarchy(pages, node=nil, options={}) + content = '' + if pages[node] + content << "
      \n" + pages[node].each do |page| + content << "
    • " + content << link_to(h(page.pretty_title), {:controller => 'wiki', :action => 'show', :project_id => page.project, :id => page.title, :version => nil}, + :title => (options[:timestamp] && page.updated_on ? l(:label_updated_time, distance_of_time_in_words(Time.now, page.updated_on)) : nil)) + content << "\n" + render_page_hierarchy(pages, page.id, options) if pages[page.id] + content << "
    • \n" + end + content << "
    \n" + end + content.html_safe + end + + # Renders flash messages + def render_flash_messages + s = '' + flash.each do |k,v| + s << content_tag('div', v.html_safe, :class => "alert alert-orange mb15 mt15", :id => "flash_#{k}") + end + s.html_safe + end + + # Renders tabs and their content + def render_tabs(tabs) + if tabs.any? + render :partial => 'common/tabs', :locals => {:tabs => tabs} + else + content_tag 'p', l(:label_no_data), :class => "nodata" + end + end + + def render_project_settings_tabs(tabs) + if tabs.any? + render :partial => 'common/project_tab', :locals => {:tabs => tabs} + else + content_tag 'p', l(:label_no_data), :class => "nodata" + end + end + + # Renders the project quick-jump box + def render_project_jump_box + return unless User.current.logged? + projects = User.current.memberships.collect(&:project).compact.select(&:active?).uniq + if projects.any? + options = + ("" + + '').html_safe + + options << project_tree_options_for_select(projects, :selected => @project) do |p| + { :value => project_path(:id => p, :jump => current_menu_item) } + end + + select_tag('project_quick_jump_box', options, :onchange => 'if (this.value != \'\') { window.location = this.value; }') + end + end + + def project_tree_options_for_select(projects, options = {}) + s = '' + project_tree(projects) do |project, level| + name_prefix = (level > 0 ? ' ' * 2 * level + '» ' : '').html_safe + tag_options = {:value => project.id} + tag_options[:title] = project.name + if project == options[:selected] || (options[:selected].respond_to?(:include?) && options[:selected].include?(project)) + tag_options[:selected] = 'selected' + else + tag_options[:selected] = nil + end + tag_options.merge!(yield(project)) if block_given? + s << content_tag('option', name_prefix + h(project), tag_options) + end + s.html_safe + end + + # Yields the given block for each project with its level in the tree + # + # Wrapper for Project#project_tree + def project_tree(projects, &block) + Project.project_tree(projects, &block) + end + + # 项目版本库可见权限判断: + # modules中设置可见 + # 版本库存在 + # 版本库设置了隐藏则仅仅项目成员或超级管理员可见(hidden_repo:1 隐藏版本库) + # return -> true 可见 + def visible_repository?(project) + repository = Repository.where(:project_id => project.id, :type => "Repository::Gitlab").first + if project.enabled_modules.where("name = 'repository'").empty? || repository.nil? + result = false + else + result = (project.hidden_repo && !User.current.admin && !User.current.member_of?(project)) ? false : true + end + end + + # 判断成员在项目中的角色 member_role == Reporter/Manager/Developer 报告人员/管理人员/报告人员; + def role_of_members_in_project(project, user_id) + member = Member.where(:project_id => project, :user_id => user_id) + unless member.blank? + member_role = member.first.roles[0].to_s + end + return member_role + end + + # 判断用户是不是项目成员 + def is_project_member?(user_id, project_id) + @result = false + mem = Member.where("user_id = ? and project_id = ?",user_id, project_id) + unless mem.blank? + @result = true + end + return @result + end + + # 更新各类消息为已读 + def update_messsages_to_viewed(message_type, forge_message_id) + if(message_type == "CourseMessage") + query = CourseMessage.where(:course_message_type => ["JoinCourse", "RemoveFromCourse"], + :user_id => User.current, + :course_id => forge_message_id, + :viewed => false) + elsif(message_type == "ForgeMessage") + query = ForgeMessage.where(:forge_message_type => ["ProjectInvite", "JoinProject", "RemoveFromProject"], + :user_id => User.current, + :project_id => forge_message_id, + :viewed => false) + elsif(message_type == "ContestMessage") + query = ContestMessage.where(:contest_message_type => ["ContestRequestDealResult", "JoinContest", "RemoveFromContest"], + :user_id => User.current, + :contest_id => forge_message_id, + :viewed => false) + elsif(message_type == "BlogMessage") + query = BlogMessage.where(:blog_message_type => "BlogComment", + :user_id => User.current, + :blog_id => forge_message_id, + :viewed => false) + end + query.update_all(:viewed => true) unless query.blank? + end + + def show_attachment_tip container_id, container_type + atts = Attachment.where(:container_id => container_id, :container_type => container_type, :is_public => 0) + atts.count > 0 ? true :false + end + + # 必须是项目成员,项目必须提交过代码 + def allow_pull_request project + return 0 if project.gpid.nil? + g = Gitlab.client + # 之所以这样比较是为了解决gitlab本身的bug + commit_count = g.project(project.gpid).try(:commit_count).to_i + git_commit_cout = g.user_static(project.gpid, :rev => "master").count + count = commit_count > git_commit_cout ? commit_count : git_commit_cout + count + end + + # 判断版本库是否初始为gitlab + def rep_is_gitlab?(project) + rep = project.repositories.where("type =?", "Repository::Gitlab") + return rep.blank? ? true :false + end + + # 获取Gitlab版本库提交总数 + def commit_count(project, branch) + g = Gitlab.client + #add by hx + if g.commits(project.gpid, :ref_name => @rev , :page=>200).count > 0 + count = 4020 + elsif g.commits(project.gpid , :page=>25, :ref_name => branch).count==0 + count = count_commits(project.gpid , 0 , 25) + elsif g.commits(project.gpid , :page=>50, :ref_name => branch).count ==0 + count = count_commits(project.gpid , 25 , 50)+ 25 * 20 + elsif g.commits(project.gpid , :page=>75, :ref_name => branch).count ==0 + count = count_commits(project.gpid , 50 , 75)+ 50 * 20 + elsif g.commits(project.gpid , :page=>100, :ref_name => branch).count== 0 + count = count_commits(project.gpid , 75 , 100) + 75 * 20 + elsif g.commits(project.gpid , :page=>125, :ref_name => branch).count==0 + count = count_commits(project.gpid , 100 , 125) + 100 * 20 + elsif g.commits(project.gpid , :page=>150, :ref_name => branch).count==0 + count = count_commits(project.gpid , 125 , 150) + 125 * 20 + else + count = count_commits(project.gpid , 150 ,200) + 150 * 20 + end + end + + #add by hx + def count_commits(project_id , left , right) + count = 0 + (left..right).each do |page| + if $g.commits(project_id,:page => page).count == 0 + break + else + count = count + $g.commits(project_id, :ref_name => @rev, :page => page).count + end + end + return count + end + + # 获取单一gitlab项目 + def gitlab_repository(project) + rep = Repository.where("project_id =? and type =?", project.id,"Repository::Gitlab" ).first + end + + # 获取单一gitlab项目 + def shixun_repository(shixun) + rep = Repository.where(:shixun_id => shixun, :type => "Repository::Gitlab" ).first + end + + # 判断当前用户是否为项目管理员 + def is_project_manager?(user_id, project_id) + @result = false + mem = Member.where("user_id = ? and project_id = ?",user_id, project_id) + unless mem.blank? + @result = mem.first.roles.to_s.include?("Manager") ? true : false + end + return @result + end + + # 公开项目资源可以引用,admin和管理员和资源上传者拥有设置公开私有权限 + def authority_pubilic_for_files(project, file) + @result = false + if (is_project_manager?(User.current.id, @project.id) && User.current.allowed_to?(:manage_files, project)) || file.author_id == User.current.id || User.current.admin && + project_contains_attachment?(project,file) && file.container_id == project.id && file.container_type == "Project" + @result = true + end + return @result + end + + def principals_check_box_tags(name, principals) + s = '' + principals.each do |principal| + s << "\n" + end + s.html_safe + end + + # 判断模块是否可见 + def project_modules_allow project + @project.enabled_modules.where("name = 'issue_tracking'").empty? + end + + # 计算Pull Request的请求数目 + def pull_request_count project + g = Gitlab.client + g.merge_requests(project.gpid).count + end + + #项目成员列表复选框生成 + def project_member_check_box_tags_ex name, principals + s = '' + principals.each do |principal| + s << "
  • #{ check_box_tag name, principal.id, false, :id => nil} #{h link_to principal.userInfo, user_url_in_org( principal), :target => "_blank"}
  • \n" + end + s.html_safe + end + + def render_shixun_departments + s = '' + if params[:q] && params[:q].lstrip.rstrip != "" + scope = School.where("name like ?", "%#{params[:q]}%") + else + scope = [] + end + scope.each do |name| + s << "
  • #{name}
  • \n" + end + s.html_safe + end + + # REDO:发现搜索列表的功能还是挺多,以前单独写的最好都调用这个方法 + # scope:[] + def render_mirror_name scope = nil + s = '' + if scope.present? + scope.each do |name| + s << "
  • #{name}
  • \n" + end + end + s.html_safe + end + + #缺陷追踪者列表复选框生成 + def issue_watcher_check_box_tags_ex name, principals + s = '' + principals.each do |principal| + s << "
  • #{ check_box_tag name, principal.id, false, :id => nil } #{h link_to principal.userInfo, user_path( principal.id)}
  • \n" + end + s.html_safe + end + + + + #扩展的checkbox生成 + def principals_check_box_tags_ex(name, principals) + s = '' + principals.each do |principal| + s << "\n" + end + s.html_safe + end + + # li标签checkbos扩展 + def principals_check_box_tags_li(name, principals) + s = '' + principals.each do |principal| + s << "
  • #{ check_box_tag name, principal.id, false, :id => nil } #{h link_to principal.userInfo, user_path( principal.id) }
  • \n" + end + s.html_safe + end + + #扩展的checkbox生成 + def principals_radio_box_tags_ex(name, principals) + s = '' + principals.each do |principal| + s << "\n" + end + s.html_safe + end + + + # Returns a string for users/groups option tags + def principals_options_for_select(collection, selected=nil) + s = '' + if collection.include?(User.current) + s << content_tag('option', "<< #{l(:label_me)} >>", :value => User.current.id) + end + groups = '' + collection.sort.each do |element| + selected_attribute = ' selected="selected"' if option_value_selected?(element, selected) + (element.is_a?(Group) ? groups : s) << %() + end + unless groups.empty? + s << %(#{groups}) + end + s.html_safe + end + + def assigned_options_for_select(collection, selected=nil) + conv = Iconv.new("GBK", "utf-8") + s = '' + s << content_tag('option', "#{l(:label_assiged_tip)}", :value => 0) + if collection.include?(User.current) + s << content_tag('option', "<< #{l(:label_me)} >>", :value => User.current.id) + end + groups = '' + collection.sort{|x, y| conv.iconv(x.lastname) <=> conv.iconv(y.lastname)}.each do |element| + selected_attribute = ' selected="selected"' if option_value_selected?(element, selected) + (element.is_a?(Group) ? groups : s) << %() + end + unless groups.empty? + s << %(#{groups}) + end + s.html_safe + end + + + # Options for the new membership projects combo-box + def options_for_membership_project_select(principal, projects) + options = content_tag('option', "--- #{l(:actionview_instancetag_blank_option)} ---") + options << project_tree_options_for_select(projects) do |p| + {:disabled => principal.projects.to_a.include?(p)} + end + options + end + + # Truncates and returns the string as a single line + def truncate_single_line(string, *args) + truncate(string.to_s, *args).gsub(%r{[\r\n]+}m, ' ') + end + + # Truncates at line break after 250 characters or options[:length] + def truncate_lines(string, options={}) + length = options[:length] || 250 + if string.to_s =~ /\A(.{#{length}}.*?)$/m + "#{$1}..." + else + string + end + end + + def anchor(text) + text.to_s.gsub(' ', '_') + end + + def html_hours(text) + text.gsub(%r{(\d+)\.(\d+)}, '\1.\2').html_safe + end + + def authoring(created, author, options={}) + l(options[:label] || :label_added_time_by, :author => link_to_user(author), :age => time_tag(created)).html_safe + end + + def added_time(created) + l(:label_added_time, :age => time_tag(created)).html_safe + end + + def user_url_and_time(user_name, user_url, created) + unless user_name.nil? || user_name == '' + l(:label_added_time_by, :author => link_to(user_name, user_url), :age => time_tag(created)).html_safe + else + l(:label_added_time, :age => time_tag(created)).html_safe + end + end + + #huang + def betweentime(enddate) + ss=(DateTime.parse("#{enddate.to_date}")-DateTime.parse("#{DateTime.now.to_date}")).to_i + return ss + end + + def time_tag(time, *args) + options = args.extract_options! + text = distance_of_time_in_words(Time.now, time) + if @project + content_tag('acronym', text, options.reverse_merge(:title => format_time(time))) + # link_to(text, {:controller => 'activities', :action => 'index', :id => @project, :from => User.current.time_to_date(time)},options.reverse_merge(:title => format_time(time))) + else + content_tag('acronym', text, options.reverse_merge(:title => format_time(time))) + end + end + + def syntax_highlight_lines(name, content) + lines = [] + syntax_highlight(name, content).each_line { |line| lines << line } + lines + end + + def syntax_highlight(name, content) + Redmine::SyntaxHighlighting.highlight_by_filename(content, name) + end + + def to_path_param(path) + str = path.to_s.split(%r{[/\\]}).select{|p| !p.blank?}.join("/") + str.blank? ? nil : str + end + + def reorder_links(name, url, method = :post) + link_to(image_tag('2uparrow.png', :alt => l(:label_sort_highest)), + url.merge({"#{name}[move_to]" => 'highest'}), + :method => method, :title => l(:label_sort_highest)) + + link_to(image_tag('1uparrow.png', :alt => l(:label_sort_higher)), + url.merge({"#{name}[move_to]" => 'higher'}), + :method => method, :title => l(:label_sort_higher)) + + link_to(image_tag('1downarrow.png', :alt => l(:label_sort_lower)), + url.merge({"#{name}[move_to]" => 'lower'}), + :method => method, :title => l(:label_sort_lower)) + + link_to(image_tag('2downarrow.png', :alt => l(:label_sort_lowest)), + url.merge({"#{name}[move_to]" => 'lowest'}), + :method => method, :title => l(:label_sort_lowest)) + end + + def breadcrumb(*args) + elements = args.flatten + elements.any? ? content_tag('p', (args.join(" \xc2\xbb ") + " \xc2\xbb ").html_safe, :class => 'wiki_con_tit"') : nil + end + + def other_formats_links(&block) + concat('

    '.html_safe + l(:label_export_to)) + yield Redmine::Views::OtherFormatsBuilder.new(self) + concat('

    '.html_safe) + end + + def page_header_title + if @project.nil? || @project.new_record? + h(Setting.app_title) + else + b = [] + ancestors = (@project.root? ? [] : @project.ancestors.visible.all) + if ancestors.any? + root = ancestors.shift + b << link_to_project(root, {:jump => current_menu_item}, :class => 'root') + if ancestors.size > 2 + b << "\xe2\x80\xa6" + ancestors = ancestors[-2, 2] + end + b += ancestors.collect {|p| link_to_project(p, {:jump => current_menu_item}, :class => 'ancestor') } + end + b << h(@project) + b.join(" \xc2\xbb ").html_safe + end + end + + def html_title(*args) + #點擊項目版本庫 多觸發一次 字符串為"/" + #暫時解決方法 直接判斷 + if(args == ["/"]) + args = [] + end + # first_page = FirstPage.find_by_page_type('project') + if args.empty? + title = @html_title || [] + if @project + title << (@project.name.present? ? @project.name : "项目") + elsif params[:controller] == "projects" + title << "项目" + elsif @welcome + title << "创新源于实践" + elsif @course + title << (@course.name.nil? ? "课堂" : @course.name) + elsif params[:controller] == "homework_bank" || params[:controller] == "question_banks" || params[:controller] == "exercise_bank" + title << ("题库") + elsif params[:controller] == "managements" + title << ("后台管理") + elsif params[:controller] == "colleges" && params[:action] == "statistics" + title << ("#{@school.name}") + elsif params[:controller] == "account" && params[:action] == "help" + if params[:index] + case params[:index] + when "1" + title << ("关于我们") + when "2" + title << ("联系我们") + when "3" + title << ("合作伙伴") + when "4" + title << ("服务协议") + when "5" + title << ("帮助中心") + when "6" + title << ("意见反馈") + end + else + title << ("关于我们") + end + elsif params[:controller] == "courses" && params[:action] == "index" + title << ("翻转课堂") + elsif params[:controller] == "competitions" && params[:action] == "index" + title << ("竞赛") + elsif @competition + title << (@competition.name.nil? ? "竞赛" : @competition.name) + elsif @contest + title << (@contest.name.nil? ? "创新源于实践" : @contest.name) + elsif @shixun + title << (@shixun.name.nil? ? "开发社区" : @shixun.name) + elsif @my_shixun + title << ("我的实训") + elsif params[:controller] == "shixuns" && params[:action] == "index" + title << ("开发社区") + elsif @subject + title << (@subject.name.nil? ? "实训课程" : @subject.name) + elsif params[:controller] == "subjects" && params[:action] == "index" + title << ("实训课程") + elsif @organization + title << (@organization.name.nil? ? "创新源于实践" : @organization.name) + elsif @forum || params[:controller] == "forums" + title << "讨论区" + elsif @my_syllabuses + title << "我的课堂" + elsif params[:controller] == 'ecs' + title << '专业列表' + elsif params[:controller] == 'ec_major_schools' + name = EcMajorSchool.find(params[:id]).name + title << name + elsif params[:controller] == 'ec_years' + if params[:action] == 'training_objectives' + title << '培养目标' + elsif params[:action] == 'graduation_requirement' + title << '毕业要求' + elsif params[:action] == 'requirement_vs_objective' + title << '毕业要求 vs 培养目标' + elsif params[:action] == 'requirement_vs_standard' + title << '毕业要求 vs 通用标准' + elsif params[:action] == 'ec_course_setting' || params[:action] == 'completion_calculation' + title << '课程体系' + else + title << '工程认证' + end + elsif params[:controller] == 'ec_courses' + if params[:action] == 'ec_course_support_setting' + title << '课程体系 vs 毕业要求' + end + elsif @user + if !@project_community.blank? || !@user_projectlist.blank? + title << "项目" + elsif !@course_community.blank? || !@user_courselist.blank? + title << "课堂" + elsif !@contest_community.blank? + title << @contest_community + elsif !@manage_issues.blank? + title << @manage_issues + elsif !@receive_issues.blank? + title << @receive_issues + elsif !@manage_homeworks.blank? + title << @manage_homeworks + elsif !@receive_homeworks.blank? + title << @receive_homeworks + else + title << @user.show_name + end + elsif @syllabus + title << (@syllabus.title.nil? ? "课堂" : @syllabus.title) + else + title << (User.current.id == 2 ? "未登录" : User.current.show_name) + end + # if first_page.nil? || first_page.web_title.nil? + # title << Setting.app_title unless Setting.app_title == title.last + # else + # title << first_page.web_title unless first_page.web_title == title.last + # end + title.select {|t| !t.blank? }.join(' - ') + else + @html_title ||= [] + @html_title += args + end + end + + # Returns the theme, controller name, and action as css classes for the + # HTML body. + def body_css_classes + css = [] + if theme = Redmine::Themes.theme(Setting.ui_theme) + css << 'theme-' + theme.name + end + + css << 'controller-' + controller_name + css << 'action-' + action_name + css.join(' ') + end + + def accesskey(s) + @used_accesskeys ||= [] + key = Redmine::AccessKeys.key_for(s) + return nil if @used_accesskeys.include?(key) + @used_accesskeys << key + key + end + + # Formats text according to system settings. + # 2 ways to call this method: + # * with a String: textilizable(text, options) + # * with an object and one of its attribute: textilizable(issue, :description, options) + def textilizable(*args) + options = args.last.is_a?(Hash) ? args.pop : {} + case args.size + when 1 + obj = options[:object] + text = args.shift + when 2 + obj = args.shift + attr = args.shift + text = obj.send(attr).to_s + else + raise ArgumentError, 'invalid arguments to textilizable' + end + return '' if text.blank? + project = options[:project] || @project || (obj && obj.respond_to?(:project) ? obj.project : nil) + only_path = options.delete(:only_path) == false ? false : true + + text = text.dup + macros = catch_macros(text) + text = Redmine::WikiFormatting.to_html(Setting.text_formatting, text, :object => obj, :attribute => attr) + + @parsed_headings = [] + @heading_anchors = {} + @current_section = 0 if options[:edit_section_links] + + parse_sections(text, project, obj, attr, only_path, options) + text = parse_non_pre_blocks(text, obj, macros) do |text| + [:parse_inline_attachments, :parse_wiki_links, :parse_redmine_links].each do |method_name| + send method_name, text, project, obj, attr, only_path, options + end + end + parse_headings(text, project, obj, attr, only_path, options) + + if @parsed_headings.any? + replace_toc(text, @parsed_headings) + end + + text.html_safe + end + + # + #格式化字符串,不转义html代码 + def textAreailizable(*args) + options = args.last.is_a?(Hash) ? args.pop : {} + case args.size + when 1 + obj = options[:object] + text = args.shift + when 2 + obj = args.shift + attr = args.shift + text = obj.send(attr).to_s + else + raise ArgumentError, 'invalid arguments to textilizable' + end + return '' if text.blank? + project = options[:project] || @project || (obj && obj.respond_to?(:project) ? obj.project : nil) + only_path = options.delete(:only_path) == false ? false : true + + text = text.dup + macros = catch_macros(text) + #text = Redmine::WikiFormatting.to_html("CKEditor", text, :object => obj, :attribute => attr) + + @parsed_headings = [] + @heading_anchors = {} + @current_section = 0 if options[:edit_section_links] + + parse_sections(text, project, obj, attr, only_path, options) + text = parse_non_pre_blocks(text, obj, macros) do |text| + [:parse_inline_attachments, :parse_wiki_links, :parse_redmine_links].each do |method_name| + send method_name, text, project, obj, attr, only_path, options + end + end + parse_headings(text, project, obj, attr, only_path, options) + + if @parsed_headings.any? + replace_toc(text, @parsed_headings) + end + + text.html_safe + end + + def parse_non_pre_blocks(text, obj, macros) + s = StringScanner.new(text) + tags = [] + parsed = '' + while !s.eos? + s.scan(/(.*?)(<(\/)?(pre|code)(.*?)>|\z)/im) + text, full_tag, closing, tag = s[1], s[2], s[3], s[4] + if tags.empty? + yield text + inject_macros(text, obj, macros) if macros.any? + else + inject_macros(text, obj, macros, false) if macros.any? + end + parsed << text + if tag + if closing + if tags.last == tag.downcase + tags.pop + end + else + tags << tag.downcase + end + parsed << full_tag + end + end + # Close any non closing tags + while tag = tags.pop + parsed << "" + end + parsed + end + + def parse_inline_attachments(text, project, obj, attr, only_path, options) + # when using an image link, try to use an attachment, if possible + attachments = options[:attachments] || [] + attachments += obj.attachments if obj.respond_to?(:attachments) + if attachments.present? + text.gsub!(/src="([^\/"]+\.(bmp|gif|jpg|jpe|jpeg|png))"(\s+alt="([^"]*)")?/i) do |m| + filename, ext, alt, alttext = $1.downcase, $2, $3, $4 + # search for the picture in attachments + if found = Attachment.latest_attach(attachments, filename) + image_url = download_named_attachment_path(found, found.filename, :only_path => only_path) + desc = found.description.to_s.gsub('"', '') + if !desc.blank? && alttext.blank? + alt = " title=\"#{desc}\" alt=\"#{desc}\"" + end + "src=\"#{image_url}\"#{alt}" + else + m + end + end + end + end + + # 判断课程、项目、组织是否有权限删除历史资源 + # 项目管理员或者附件的作者可以删除 + # (is_project_manager?(User.current.id, @project.id) || User.current.id == history.author_id) + def allow_to_delete_attachment history + attachment = history.attachment + case attachment.try(:container_type) + when "Project" + result = is_project_manager?(User.current.id, attachment.container_id) || User.current.id == history.author_id || User.current.admin? + when "Course" + result = User.current.allowed_to?(:as_teacher, attachment.container) || User.current.id == history.author_id || User.current.admin? + when "OrgSubfield" + result = User.current.id == history.author_id || User.current.admin_of_org?(attachment.container) || User.current.admin? + end + end + + # Wiki links + # + # Examples: + # [[mypage]] + # [[mypage|mytext]] + # wiki links can refer other project wikis, using project name or identifier: + # [[project:]] -> wiki starting page + # [[project:|mytext]] + # [[project:mypage]] + # [[project:mypage|mytext]] + def parse_wiki_links(text, project, obj, attr, only_path, options) + text.gsub!(/(!)?(\[\[([^\]\n\|]+)(\|([^\]\n\|]+))?\]\])/) do |m| + link_project = project + esc, all, page, title = $1, $2, $3, $5 + if esc.nil? + if page =~ /^([^\:]+)\:(.*)$/ + identifier, page = $1, $2 + link_project = Project.find_by_identifier(identifier) || Project.find_by_name(identifier) + title ||= identifier if page.blank? + end + + if link_project && link_project.wiki + # extract anchor + anchor = nil + if page =~ /^(.+?)\#(.+)$/ + page, anchor = $1, $2 + end + anchor = sanitize_anchor_name(anchor) if anchor.present? + # check if page exists + wiki_page = link_project.wiki.find_page(page) + url = if anchor.present? && wiki_page.present? && (obj.is_a?(WikiContent) || obj.is_a?(WikiContent::Version)) && obj.page == wiki_page + "##{anchor}" + else + case options[:wiki_links] + when :local; "#{page.present? ? Wiki.titleize(page) : ''}.html" + (anchor.present? ? "##{anchor}" : '') + when :anchor; "##{page.present? ? Wiki.titleize(page) : title}" + (anchor.present? ? "_#{anchor}" : '') # used for single-file wiki export + else + wiki_page_id = page.present? ? Wiki.titleize(page) : nil + parent = wiki_page.nil? && obj.is_a?(WikiContent) && obj.page && project == link_project ? obj.page.title : nil + url_for(:only_path => only_path, :controller => 'wiki', :action => 'show', :project_id => link_project, + :id => wiki_page_id, :version => nil, :anchor => anchor, :parent => parent) + end + end + link_to(title.present? ? title.html_safe : h(page), User.current.logged? ? url : signin_url_without_domain, :class => ('wiki-page' + (wiki_page ? '' : ' new'))) + else + # project or wiki doesn't exist + all + end + else + all + end + end + end + + def select_option_helper option + tmp = Hash.new + tmp={"" => ""} + if option.nil? + else + option.each do |project| + tmp[project.name] = project.id + end + end + tmp + end + # Redmine links + # + # Examples: + # Issues: + # #52 -> Link to issue #52 + # Changesets: + # r52 -> Link to revision 52 + # commit:a85130f -> Link to scmid starting with a85130f + # Documents: + # document#17 -> Link to document with id 17 + # document:Greetings -> Link to the document with title "Greetings" + # document:"Some document" -> Link to the document with title "Some document" + # Versions: + # version#3 -> Link to version with id 3 + # version:1.0.0 -> Link to version named "1.0.0" + # version:"1.0 beta 2" -> Link to version named "1.0 beta 2" + # Attachments: + # attachment:file.zip -> Link to the attachment of the current object named file.zip + # Source files: + # source:some/file -> Link to the file located at /some/file in the project's repository + # source:some/file@52 -> Link to the file's revision 52 + # source:some/file#L120 -> Link to line 120 of the file + # source:some/file@52#L120 -> Link to line 120 of the file's revision 52 + # export:some/file -> Force the download of the file + # Forum messages: + # message#1218 -> Link to message with id 1218 + # + # Links can refer other objects from other projects, using project identifier: + # identifier:r52 + # identifier:document:"Some document" + # identifier:version:1.0.0 + # identifier:source:some/file + def parse_redmine_links(text, default_project, obj, attr, only_path, options) + text.gsub!(%r{([\s\(,\-\[\>]|^)(!)?(([a-z0-9\-_]+):)?(attachment|document|version|forum|news|message|project|commit|source|export)?(((#)|((([a-z0-9\-_]+)\|)?(r)))((\d+)((#note)?-(\d+))?)|(:)([^"\s<>][^\s<>]*?|"[^"]+?"))(?=(?=[[:punct:]][^A-Za-z0-9_/])|,|\s|\]|<|$)}) do |m| + leading, esc, project_prefix, project_identifier, prefix, repo_prefix, repo_identifier, sep, identifier, comment_suffix, comment_id = $1, $2, $3, $4, $5, $10, $11, $8 || $12 || $18, $14 || $19, $15, $17 + link = nil + project = default_project + if project_identifier + project = Project.visible.find_by_identifier(project_identifier) + end + if esc.nil? + if prefix.nil? && sep == 'r' + if project + repository = nil + if repo_identifier + repository = project.repositories.detect {|repo| repo.identifier == repo_identifier} + else + repository = project.repository + end + # project.changesets.visible raises an SQL error because of a double join on repositories + if repository && (changeset = Changeset.visible.find_by_repository_id_and_revision(repository.id, identifier)) + link = link_to(h("#{project_prefix}#{repo_prefix}r#{identifier}"), {:only_path => only_path, :controller => 'repositories', :action => 'revision', :id => project, :repository_id => repository.identifier_param, :rev => changeset.revision}, + :class => 'changeset', + :title => truncate_single_line(changeset.comments, :length => 100)) + end + end + elsif sep == '#' + oid = identifier.to_i + case prefix + when nil + if oid.to_s == identifier && issue = Issue.visible.find_by_id(oid, :include => :status) + anchor = comment_id ? "note-#{comment_id}" : nil + link = link_to("##{oid}", {:only_path => only_path, :controller => 'issues', :action => 'show', :id => oid, :anchor => anchor}, + :class => issue.css_classes, + :title => "#{truncate(issue.subject, :length => 100)} (#{issue.status.name})") + end + when 'document' + if document = Document.visible.find_by_id(oid) + link = link_to h(document.title), {:only_path => only_path, :controller => 'documents', :action => 'show', :id => document}, + :class => 'document' + end + when 'version' + if version = Version.visible.find_by_id(oid) + link = link_to h(version.name), {:only_path => only_path, :controller => 'versions', :action => 'show', :id => version}, + :class => 'version' + end + when 'message' + if message = Message.visible.find_by_id(oid, :include => :parent) + link = link_to_message(message, {:only_path => only_path}, :class => 'message') + end + when 'forum' + if board = Board.visible.find_by_id(oid) + link = link_to h(board.name), {:only_path => only_path, :controller => 'boards', :action => 'show', :id => board, :project_id => board.project}, + :class => 'board' + end + when 'news' + if news = News.visible.find_by_id(oid) + link = link_to h(news.title), {:only_path => only_path, :controller => 'news', :action => 'show', :id => news}, + :class => 'news' + end + when 'project' + if p = Project.visible.find_by_id(oid) + link = link_to_project(p, {:only_path => only_path}, :class => 'project') + end + end + elsif sep == ':' + # removes the double quotes if any + name = identifier.gsub(%r{^"(.*)"$}, "\\1") + case prefix + when 'document' + if project && document = project.documents.visible.find_by_title(name) + link = link_to h(document.title), {:only_path => only_path, :controller => 'documents', :action => 'show', :id => document}, + :class => 'document' + end + when 'version' + if project && version = project.versions.visible.find_by_name(name) + link = link_to h(version.name), {:only_path => only_path, :controller => 'versions', :action => 'show', :id => version}, + :class => 'version' + end + when 'forum' + if project && board = project.boards.visible.find_by_name(name) + link = link_to h(board.name), {:only_path => only_path, :controller => 'boards', :action => 'show', :id => board, :project_id => board.project}, + :class => 'board' + end + when 'news' + if project && news = project.news.visible.find_by_title(name) + link = link_to h(news.title), {:only_path => only_path, :controller => 'news', :action => 'show', :id => news}, + :class => 'news' + end + when 'commit', 'source', 'export' + if project + repository = nil + if name =~ %r{^(([a-z0-9\-_]+)\|)(.+)$} + repo_prefix, repo_identifier, name = $1, $2, $3 + repository = project.repositories.detect {|repo| repo.identifier == repo_identifier} + else + repository = project.repository + end + if prefix == 'commit' + if repository && (changeset = Changeset.visible.where("repository_id = ? AND scmid LIKE ?", repository.id, "#{name}%").first) + link = link_to h("#{project_prefix}#{repo_prefix}#{name}"), {:only_path => only_path, :controller => 'repositories', :action => 'revision', :id => project, :repository_id => repository.identifier_param, :rev => changeset.identifier}, + :class => 'changeset', + :title => truncate_single_line(changeset.comments, :length => 100) + end + else + if repository && User.current.allowed_to?(:browse_repository, project) + name =~ %r{^[/\\]*(.*?)(@([^/\\@]+?))?(#(L\d+))?$} + path, rev, anchor = $1, $3, $5 + link = link_to h("#{project_prefix}#{prefix}:#{repo_prefix}#{name}"), {:controller => 'repositories', :action => (prefix == 'export' ? 'raw' : 'entry'), :id => project, :repository_id => repository.identifier_param, + :path => to_path_param(path), + :rev => rev, + :anchor => anchor}, + :class => (prefix == 'export' ? 'source download' : 'source') + end + end + repo_prefix = nil + end + when 'attachment' + attachments = options[:attachments] || (obj && obj.respond_to?(:attachments) ? obj.attachments : nil) + if attachments && attachment = Attachment.latest_attach(attachments, name) + link = link_to_attachment(attachment, :only_path => only_path, :download => true, :class => 'attachment') + end + when 'project' + if p = Project.visible.where("identifier = :s OR LOWER(name) = :s", :s => name.downcase).first + link = link_to_project(p, {:only_path => only_path}, :class => 'project') + end + end + end + end + (leading + (link || "#{project_prefix}#{prefix}#{repo_prefix}#{sep}#{identifier}#{comment_suffix}")) + end + end + + HEADING_RE = /(]+)?>(.+?)<\/h(\d)>)/i unless const_defined?(:HEADING_RE) + + def parse_sections(text, project, obj, attr, only_path, options) + return unless options[:edit_section_links] + text.gsub!(HEADING_RE) do + heading = $1 + @current_section += 1 + if @current_section > 1 + content_tag('div', + link_to(image_tag('edit.png'), options[:edit_section_links].merge(:section => @current_section)), + :class => 'contextual', + :title => l(:button_edit_section)) + heading.html_safe + else + heading + end + end + end + + # Headings and TOC + # Adds ids and links to headings unless options[:headings] is set to false + def parse_headings(text, project, obj, attr, only_path, options) + return if options[:headings] == false + + text.gsub!(HEADING_RE) do + level, attrs, content = $2.to_i, $3, $4 + item = strip_tags(content).strip + anchor = sanitize_anchor_name(item) + # used for single-file wiki export + anchor = "#{obj.page.title}_#{anchor}" if options[:wiki_links] == :anchor && (obj.is_a?(WikiContent) || obj.is_a?(WikiContent::Version)) + @heading_anchors[anchor] ||= 0 + idx = (@heading_anchors[anchor] += 1) + if idx > 1 + anchor = "#{anchor}-#{idx}" + end + @parsed_headings << [level, anchor, item] + "\n#{content}" + end + end + + MACROS_RE = /( + (!)? # escaping + ( + \{\{ # opening tag + ([\w]+) # macro name + (\(([^\n\r]*?)\))? # optional arguments + ([\n\r].*?[\n\r])? # optional block of text + \}\} # closing tag + ) + )/mx unless const_defined?(:MACROS_RE) + + MACRO_SUB_RE = /( + \{\{ + macro\((\d+)\) + \}\} + )/x unless const_defined?(:MACRO_SUB_RE) + + # Extracts macros from text + def catch_macros(text) + macros = {} + text.gsub!(MACROS_RE) do + all, macro = $1, $4.downcase + if macro_exists?(macro) || all =~ MACRO_SUB_RE + index = macros.size + macros[index] = all + "{{macro(#{index})}}" + else + all + end + end + macros + end + + # Executes and replaces macros in text + def inject_macros(text, obj, macros, execute=true) + text.gsub!(MACRO_SUB_RE) do + all, index = $1, $2.to_i + orig = macros.delete(index) + if execute && orig && orig =~ MACROS_RE + esc, all, macro, args, block = $2, $3, $4.downcase, $6.to_s, $7.try(:strip) + if esc.nil? + h(exec_macro(macro, obj, args, block) || all) + else + h(all) + end + elsif orig + h(orig) + else + h(all) + end + end + end + + TOC_RE = /

    \{\{([<>]?)toc\}\}<\/p>/i unless const_defined?(:TOC_RE) + + # Renders the TOC with given headings + def replace_toc(text, headings) + text.gsub!(TOC_RE) do + # Keep only the 4 first levels + headings = headings.select{|level, anchor, item| level <= 4} + if headings.empty? + '' + else + div_class = 'toc' + div_class << ' right' if $1 == '>' + div_class << ' left' if $1 == '<' + out = "

    • " + root = headings.map(&:first).min + current = root + started = false + headings.each do |level, anchor, item| + if level > current + out << '
      • ' * (level - current) + elsif level < current + out << "
      \n" * (current - level) + "
    • " + elsif started + out << '
    • ' + end + out << "#{item}" + current = level + started = true + end + out << '
    ' * (current - root) + out << '' + end + end + end + + # Same as Rails' simple_format helper without using paragraphs + def simple_format_without_paragraph(text) + text.to_s. + gsub(/\r\n?/, "\n"). # \r\n and \r -> \n + gsub(/\n\n+/, "

    "). # 2+ newline -> 2 br + gsub(/([^\n]\n)(?=[^\n])/, '\1
    '). # 1 newline -> br + html_safe + end + + def wiki_simple_format_without_paragraph(text) + text.to_s. + gsub(/\r\n?/, "\n"). # \r\n and \r -> \n + gsub(/\n\n+/, "

    "). # 2+ newline -> 2 br + gsub(/([^\n]\n)(?=[^\n])/, '\1
    '). # 1 newline -> br + gsub("&nbsp", " "). #gsub(/<\/?.*?>/,""). + gsub(/<\/?.*?>/, ""). + gsub(""", "'"). + html_safe + end + + def lang_options_for_select(blank=true) + { 'Chinese简体中文 '=> 'zh', :English => :en} + end + + def label_tag_for(name, option_tags = nil, options = {}) + label_text = l(("field_"+field.to_s.gsub(/\_id$/, "")).to_sym) + (options.delete(:required) ? @template.content_tag("span", " *", :class => "required"): "") + content_tag("label", label_text) + end + + def labelled_form_for(*args, &proc) + args << {} unless args.last.is_a?(Hash) + options = args.last + if args.first.is_a?(Symbol) + options.merge!(:as => args.shift) + end + options.merge!({:builder => Redmine::Views::LabelledFormBuilder}) + form_for(*args, &proc) + end + + def labelled_fields_for(*args, &proc) + args << {} unless args.last.is_a?(Hash) + options = args.last + options.merge!({:builder => Redmine::Views::LabelledFormBuilder}) + fields_for(*args, &proc) + end + + def labelled_remote_form_for(*args, &proc) + ActiveSupport::Deprecation.warn "ApplicationHelper#labelled_remote_form_for is deprecated and will be removed in Redmine 2.2." + args << {} unless args.last.is_a?(Hash) + options = args.last + options.merge!({:builder => Redmine::Views::LabelledFormBuilder, :remote => true}) + form_for(*args, &proc) + end + + def error_messages_for(*objects) + html = "" + # modified by fq + if objects.first.is_a?(Array) + objects = objects.first + end + # end + if objects != nil + objects = objects.map {|o| o.is_a?(String) ? instance_variable_get("@#{o}") : o}.compact + errors = objects.map {|o| o.errors.full_messages}.flatten + if errors.any? + html << "
      \n" + errors.each do |error| + ###by xianbo + if(error!=l(:label_repository_path_not_null)) + html << "
    • #{h error}
    • \n" + end + ###xianbo + end + ###by xianbo + unless params[:repository].nil? + if params[:repository][:upassword]=="" + html << "
    • "+ l(:label_password_not_null) +"
    • \n" + end + end + ###xianbo + html << "
    \n" + end + end + html.html_safe + end + + def delete_link(url, options={}) + options = { + :method => :delete, + :data => {:confirm => l(:text_are_you_sure)}, + :class => 'icon icon-del' + }.merge(options) + + link_to l(:button_delete), url, options + end + + def update_status_link(user) + url = {:controller => 'users', :action => 'update', :id => user, :page => params[:page], :status => params[:status], :tab => nil} + + if user.locked? + link_to "解锁", url.merge(:user => {:status => User::STATUS_ACTIVE}), :method => :put, :class => 'mr10 link-color-blue' + elsif user.registered? + link_to "激活", url.merge(:user => {:status => User::STATUS_ACTIVE}), :method => :put, :class => 'mr10 link-color-blue' + elsif user != User.current + link_to "加锁", url.merge(:user => {:status => User::STATUS_LOCKED}), :method => :put, :class => 'mr10 link-color-blue' + end + end + + + def delete_version_link(url, options={}) + options = { + :method => :delete, + :data => {:confirm => l(:text_are_you_sure)}, + :class => 'icon icon-del' + }.merge(options) + + link_to "", url, options + end + + def delete_link_version(url, options={}) + options = { + :method => :delete, + :data => {:confirm => l(:text_are_you_sure)}, + :class => 'c_purple' + }.merge(options) + + link_to l(:button_delete), url, options + end + + + + def delete_new_link(url, options={}) + options = { + :method => :delete, + :data => {:confirm => l(:text_are_you_sure)}, + :class => "c_purple" + }.merge(options) + + link_to l(:button_delete), url, options + end + + def preview_link(url, form, target='preview', options={}) + content_tag 'a', l(:label_preview), { + :href => "#", + :onclick => %|submitPreview("#{escape_javascript url_for(url)}", "#{escape_javascript form}", "#{escape_javascript target}"); return false;|, + :accesskey => accesskey(:preview) + }.merge(options) + end + + def link_to_function(name, function, html_options={}) + content_tag(:a, name, {:href => '#', :onclick => "#{function}; return false;"}.merge(:class => "BlueCirBtnMini ml10",:style => "display:inline-block; height:20px; line-height:20px;")) + end + + def link_to_function_none(name, function, html_options={}) + content_tag(:a, name, {:href => '#', :onclick => "#{function}; return false;"}.merge(:style => "display:inline-block; height:20px; line-height:20px;")) + end + + # Helper to render JSON in views + def raw_json(arg) + arg.to_json.to_s.gsub('/', '\/').html_safe + end + + def back_url + url = params[:back_url] + if url.nil? && referer = request.env['HTTP_REFERER'] + url = CGI.unescape(referer.to_s) + end + url + end + + def back_url_hidden_field_tag + url = back_url + hidden_field_tag('back_url', url, :id => nil) unless url.blank? + end + + def check_all_links(form_name) + link_to_function_none(l(:button_check_all), "checkAll('#{form_name}', true)") + " ".html_safe + " | "+ " ".html_safe + + link_to_function_none(l(:button_uncheck_all), "checkAll('#{form_name}', false)") + end + + # 本次修改,修改为只显示关闭的所占%比 + def progress_bar(pcts, options={}) + pcts = [pcts] unless pcts.is_a?(Array) + pcts = pcts.collect(&:round) + # pcts[1] = pcts[1] + pcts[0] + pcts << (100 - pcts[0]) + width = options[:width] || '100px;' + legend = options[:legend] || '' + content_tag('span', + content_tag('tr', + (pcts[0] > 0 ? content_tag('span', '', :style => "width: #{pcts[0]}%;", :class => 'roadmap_progressbar_inner', :title => "已关闭:#{pcts[0]}%") : ''.html_safe) #+ + # (pcts[1] > 0 ? content_tag('td', '', :style => "width: #{pcts[1]}%;", :class => 'done', :title => "开发中:#{pcts[1]}%") : ''.html_safe) + + #(pcts[1] > 0 ? content_tag('span', '', :style => "width: #{pcts[1]}%;", :class => 'roadmap_progressbar ml5', :title => "未完成:#{pcts[1]}%") : ''.html_safe), :style => "width: #{width}" + ), :class => 'roadmap_progressbar ml5').html_safe + # + content_tag('p', legend, :class => 'percent').html_safe + end + + def checked_image(checked=true) + if checked + image_tag 'toggle_check.png' + end + end + + def context_menu(url) + unless @context_menu_included + content_for :header_tags do + javascript_include_tag('context_menu') + + stylesheet_link_tag('context_menu') + end + if l(:direction) == 'rtl' + content_for :header_tags do + stylesheet_link_tag('context_menu_rtl') + end + end + @context_menu_included = true + end + javascript_tag "contextMenuInit('#{ url_for(url) }')" + end + + def calendar_for(field_id,start_day=nil) + include_calendar_headers_tags(start_day) + javascript_tag("$(function() { $('##{field_id}').datepicker(datepickerOptions); });") + end + + def include_calendar_headers_tags(start_day=nil) + if start_day.nil? + unless @calendar_headers_tags_included + @calendar_headers_tags_included = true + content_for :header_tags do + start_of_week = Setting.start_of_week + start_of_week = l(:general_first_day_of_week, :default => '1') if start_of_week.blank? + # Redmine uses 1..7 (monday..sunday) in settings and locales + # JQuery uses 0..6 (sunday..saturday), 7 needs to be changed to 0 + start_of_week = start_of_week.to_i % 7 + + tags = javascript_tag( + "var datepickerOptions={dateFormat: 'yy-mm-dd', firstDay: #{start_of_week}, " + + "showOn: 'button', buttonImageOnly: true, buttonImage: '" + + path_to_image('/images/public_icon.png') + + "', showButtonPanel: true, showWeek: true, showOtherMonths: true, selectOtherMonths: true};") + jquery_locale = l('jquery.locale', :default => current_language.to_s) + unless jquery_locale == 'en' + tags << javascript_include_tag("i18n/jquery.ui.datepicker-#{jquery_locale}.js") + end + tags + end + end + else + unless @calendar_headers_tags_included + @calendar_headers_tags_included = true + content_for :header_tags do + start_of_week = Setting.start_of_week + start_of_week = l(:general_first_day_of_week, :default => '1') if start_of_week.blank? + # Redmine uses 1..7 (monday..sunday) in settings and locales + # JQuery uses 0..6 (sunday..saturday), 7 needs to be changed to 0 + start_of_week = start_of_week.to_i % 7 + + tags = javascript_tag( + "var datepickerOptions={dateFormat: 'yy-mm-dd',minDate: new Date(), firstDay: #{start_of_week}, " + + "showOn: 'button', buttonImageOnly: true, buttonImage: '" + + path_to_image('/images/public_icon.png') + + "', showButtonPanel: true, showWeek: true, showOtherMonths: true, selectOtherMonths: true, onClose: function(dateText, inst) {TimeClose(dateText,inst);}, beforeShow : function(input){TimeBeforeShow(input);} };") + jquery_locale = l('jquery.locale', :default => current_language.to_s) + unless jquery_locale == 'en' + tags << javascript_include_tag("i18n/jquery.ui.datepicker-#{jquery_locale}.js") + end + tags + end + end + end + + end + + # Overrides Rails' stylesheet_link_tag with themes and plugins support. + # Examples: + # stylesheet_link_tag('styles') # => picks styles.css from the current theme or defaults + # stylesheet_link_tag('styles', :plugin => 'foo) # => picks styles.css from plugin's assets + # + def stylesheet_link_tag(*sources) + options = sources.last.is_a?(Hash) ? sources.pop : {} + plugin = options.delete(:plugin) + sources = sources.map do |source| + if plugin + "/plugin_assets/#{plugin}/stylesheets/#{source}" + elsif current_theme && current_theme.stylesheets.include?(source) + current_theme.stylesheet_path(source) + else + source + end + end + super sources, options + end + + # Overrides Rails' image_tag with themes and plugins support. + # Examples: + # image_tag('image.png') # => picks image.png from the current theme or defaults + # image_tag('image.png', :plugin => 'foo) # => picks image.png from plugin's assets + # + def image_tag(source, options={}) + if plugin = options.delete(:plugin) + source = "/plugin_assets/#{plugin}/images/#{source}" + elsif current_theme && current_theme.images.include?(source) + source = current_theme.image_path(source) + end + super source, options + end + + # Overrides Rails' javascript_include_tag with plugins support + # Examples: + # javascript_include_tag('scripts') # => picks scripts.js from defaults + # javascript_include_tag('scripts', :plugin => 'foo) # => picks scripts.js from plugin's assets + # + def javascript_include_tag(*sources) + options = sources.last.is_a?(Hash) ? sources.pop : {} + + @sources ||= [] + sources = sources.delete_if do|source| + @sources.include?(source) + end + @sources += sources + + if plugin = options.delete(:plugin) + sources = sources.map do |source| + if plugin + "/plugin_assets/#{plugin}/javascripts/#{source}" + else + source + end + end + end + + if sources && !sources.empty? + super(sources, options) + else + '' + end + end + + def content_for(name, content = nil, &block) + @has_content ||= {} + @has_content[name] = true + super(name, content, &block) + end + + def has_content?(name) + (@has_content && @has_content[name]) || false + end + + def sidebar_content? + has_content?(:sidebar) || view_layouts_base_sidebar_hook_response.present? + end + + def view_layouts_base_sidebar_hook_response + @view_layouts_base_sidebar_hook_response ||= call_hook(:view_layouts_base_sidebar) + end + + def email_delivery_enabled? + !!ActionMailer::Base.perform_deliveries + end + + # Returns the avatar image tag for the given +user+ if avatars are enabled + # +user+ can be a User or a string that will be scanned for an email address (eg. 'joe ') + def avatar(user, options = { }) + if Setting.gravatar_enabled? + options.merge!({:ssl => (request && request.ssl?), :default => Setting.gravatar_default}) + email = nil + if user.respond_to?(:mail) + email = user.mail + elsif user.to_s =~ %r{<(.+?)>} + email = $1 + end + return gravatar(email.to_s.downcase, options) unless email.blank? rescue nil + #options ={"class" => ["avatar2"],"width" =>["80px"],"height" =>["80px"]} + #return image_tag url_to_avatar(user), options + else + '' + end + end + + def sanitize_anchor_name(anchor) + if ''.respond_to?(:encoding) || RUBY_PLATFORM == 'java' + anchor.gsub(%r{[^\s\-\p{Word}]}, '').gsub(%r{\s+(\-+\s*)?}, '-') + else + # TODO: remove when ruby1.8 is no longer supported + anchor.gsub(%r{[^\w\s\-]}, '').gsub(%r{\s+(\-+\s*)?}, '-') + end + end + + # Returns the javascript tags that are included in the html layout head + def javascript_heads + tags = javascript_include_tag('jquery-1.8.3-ui-1.9.2-ujs-2.0.3', 'application','jquery.colorbox-min', 'baiduTemplate') + unless User.current.pref.warn_on_leaving_unsaved == '0' + tags << "\n".html_safe + javascript_tag("$(window).load(function(){ warnLeavingUnsaved('#{escape_javascript l(:text_warn_on_leaving_unsaved)}'); });") + end + tags + end + def javascript_edu_index_heads + tags = javascript_include_tag('jquery-1.8.3-ui-1.9.2-ujs-2.0.3', 'application') + unless User.current.pref.warn_on_leaving_unsaved == '0' + tags << "\n".html_safe + javascript_tag("$(window).load(function(){ warnLeavingUnsaved('#{escape_javascript l(:text_warn_on_leaving_unsaved)}'); });") + end + tags + end + + # 临时本地版 + def javascript_heads_local + tags = javascript_include_tag('jquery-1.8.3-ui-1.9.2-ujs-2.0.3', 'jquery.colorbox-min') + unless User.current.pref.warn_on_leaving_unsaved == '0' + tags << "\n".html_safe + javascript_tag("$(window).load(function(){ warnLeavingUnsaved('#{escape_javascript l(:text_warn_on_leaving_unsaved)}'); });") + end + tags + end + + def hubspot_head + tags = javascript_include_tag('hubspot/messenger.min', 'hubspot/messenger-theme-future') + tags << stylesheet_link_tag('hubspot/messenger', 'hubspot/messenger-theme-future', 'hubspot/messenger-theme-flat') + end + + def bootstrap_head + tags = stylesheet_link_tag('bootstrap/bootstrap.min', 'bootstrap/bootstrap-theme.min') + tags << javascript_include_tag('bootstrap/affix') + tags << javascript_include_tag('bootstrap/alert') + tags << javascript_include_tag('bootstrap/button') + tags << javascript_include_tag('bootstrap/carousel') + tags << javascript_include_tag('bootstrap/collapse') + tags << javascript_include_tag('bootstrap/dropdown') + tags << javascript_include_tag('bootstrap/modal') + tags << javascript_include_tag('bootstrap/popover') + tags << javascript_include_tag('bootstrap/scrollspy') + tags << javascript_include_tag('bootstrap/tab') + tags << javascript_include_tag('bootstrap/tooltip') + tags << javascript_include_tag('bootstrap/transition') + tags + end + + def favicon + "".html_safe + end + + def robot_exclusion_tag + ''.html_safe + end + + # Returns true if arg is expected in the API response + def include_in_api_response?(arg) + unless @included_in_api_response + param = params[:include] + @included_in_api_response = param.is_a?(Array) ? param.collect(&:to_s) : param.to_s.split(',') + @included_in_api_response.collect!(&:strip) + end + @included_in_api_response.include?(arg.to_s) + end + + # Returns options or nil if nometa param or X-Redmine-Nometa header + # was set in the request + def api_meta(options) + if params[:nometa].present? || request.headers['X-Redmine-Nometa'] + # compatibility mode for activeresource clients that raise + # an error when unserializing an array with attributes + nil + else + options + end + end + + # Add by Tao + def url_to_avatar(source) + source = nil if source.kind_of?(String) + get_avatar(source) + end + # Endof Tao's code + + # cxt + # 获取认证照片 + def url_to_auth_img(user_id, type) + if File.exist?(disk_auth_filename("UserAuthentication",user_id,type)) + File.join(relative_path,avatar_directory("UserAuthentication"), auth_filename(user_id,type)) + else + File.join(relative_path,avatar_directory("UserAuthentication"),type) + end + end + + def url_to_coop_img(type) + File.join(relative_path,avatar_directory('type'),"*") + end + + # 讨论区的平台icon ["Java", "C", "C++", "Python2.7", "Python3.6", "MySQL/Java", "Html", "JFinal", "Docker", "Ethereum", "Dynamips", "MachineLearning", "Verilog","Spark","MySQL/Python3.6","PHP","PHP/Web","Hadoop", "Golang","Android","Matlab","Shell"] + + def url_to_platform_icon language + case language + when 'Python2.7', 'Python3.6' + File.join(relative_path,avatar_directory("Platform"), 'Python') + when 'MySQL/Java', 'MySQL/Python3.6' + File.join(relative_path,avatar_directory("Platform"), 'MySQL') + when 'PHP/Web' + File.join(relative_path,avatar_directory("Platform"), 'PHP') + when 'C#' + File.join(relative_path,avatar_directory("Platform"), 'Cxp') + when 'C/C++' + File.join(relative_path,avatar_directory("Platform"), 'Cjia') + when 'Angular2+' + File.join(relative_path,avatar_directory("Platform"), 'Angular2jia') + else + File.join(relative_path,avatar_directory("Platform"), language.nil? ? "" : language) + end + end + + def identity_authentication_status user + authorization = user.apply_actions.where(:container_type => "TrialAuthorization").last + case user.try(:certification) + when 0 + if authorization.try(:status) == 0 + "处理中" + else + "未授权" + end + when 1 + "已授权" + when 2 + "被拒绝" + end + end + + def user_certification_status user + status = "" + if user.authentication + status = "已实名认证" + else + apply_auth = ApplyUserAuthentication.where(:user_id => user.id, :auth_type => 1).last + if apply_auth && apply_auth.status == 0 + status = "实名认证中" + elsif apply_auth && apply_auth.status == 2 + status = "实名认证未通过" + else + status = "未实名认证" + end + end + end + + def pro_certification_status user + status = "" + if user.professional_certification + status = "已职业认证" + else + apply_auth = ApplyUserAuthentication.where(:user_id => user.id, :auth_type => 2).last + if apply_auth && apply_auth.status == 0 + status = "职业认证中" + elsif apply_auth && apply_auth.status == 2 + status = "职业认证未通过" + else + status = "未职业认证" + end + end + end + + def shixun_authentication_status shixun + case shixun.try(:status) + when 0,nil + "编辑中" + when 1 + "待审核" + when 2 + "已发布" + when 3 + "已关闭" + end + end + + def date_format_local(time) + date = time.strftime("%Y年%m月%d日") + end + + #当TAG数量过多时,更多链接 + #1代表是user类型 2代表是project类型 3代表是issue类型 4代表需求 9代表课程 + def more_tags id,object_flag + a= 1 + case object_flag + when "1" + s = link_to l(:label_more_tags),:controller => "users", :action => "show", :id => id + when "2" + s = link_to l(:label_more_tags),:controller => "projects", :action => "show", :id => id + when "3" + s = link_to l(:label_more_tags),:controller => "issues", :action => "show", :id => id + when "4" + s = link_to l(:label_more_tags),:controller => "bids", :action => "show", :id => id + when "9" + s = link_to l(:label_more_tags),:controller => "courses", :action => "show", :id => id + end + s + end + + def get_user_identity identity + s = "" + case identity + when 0 + s = '教师' + when 1 + s = '学生' + when 2 + s = '组织' + when 3 + s= '开发者' + else + s = '学生' + end + s + end + + # 获取issue类型 + def get_issue_type_new tracker_id + case tracker_id + when 1 + "缺陷" + when 2 + "功能" + when 3 + "支持" + when 4 + "任务" + when 5 + "周报" + end + end + + def get_memo + @new_memo = Memo.new + @public_forum = Forum.find(1) rescue ActiveRecord::RecordNotFound + end + + #获取用户未过期的课程 + def get_user_course user + courses_doing = [] + user.courses.select("courses.*,(SELECT MAX(created_at) FROM `course_activities` WHERE course_activities.course_id = courses.id) AS a").order("a desc").each do |course| + if !course_endTime_timeout?(course) + courses_doing.push course + end + end + courses_doing + end + + def attachment_history_candown attachment_history + if attachment_history.container_type == "Course" + course = Course.find(attachment_history.container_id) + candown = User.current.member_of_course?(course) || (course.is_public && attachment_history.is_public == 1) + elsif attachment_history.container_type == "Project" + project = Project.find(attachment_history.container_id) + candown = User.current.member_of?(project) || (project.is_public && attachment_history.is_public == 1) + elsif attachment_history.container_type == "OrgSubfield" + org = OrgSubfield.find(attachment_history.container_id).organization + candown = User.current.member_of_org?(org) || (org.organization.is_public && attachment_history.is_public == 1 && (User.current.logged? || org.organization.allow_guest_download?)) + end + end + + def resource_bank_candown resource,type + candown = false + if resource.is_public + candown = true + end + if type == 'syllabus' + candown = syllabus_course_member(User.current, resource.course) || User.current.admin? + end + candown + end + + # 课程某个班级的成员 + def syllabus_course_member user, course + result = false + syllabus = course.syllabus + if syllabus + syllabus.courses.each do |course| + if user.member_of_course?(course) + result = true + return result + end + end + end + result + end + + def attachment_candown attachment + candown = false + if attachment.container + if attachment.container.class.to_s=="PhoneAppVersion" + candown = true + elsif attachment.container.class.to_s != "HomeworkAttach" && attachment.container.class.to_s != "StudentWork" && attachment.container.class.to_s != "ContestantWork" && (attachment.container.has_attribute?(:project) || attachment.container.has_attribute?(:project_id)) && attachment.container.project + project = attachment.container.project + candown= User.current.member_of?(project) || (project.is_public && attachment.is_public == 1) + elsif attachment.container.is_a?(Project) + project = attachment.container + candown = User.current.member_of?(project) || (attachment.is_public == 1) || attachment.get_status_by_attach(User.current.id) == 2 + elsif (attachment.container.has_attribute?(:board) || attachment.container.has_attribute?(:board_id)) && attachment.container.board && + attachment.container.board.project + project = attachment.container.board.project + candown = User.current.member_of?(project) || (project.is_public && attachment.is_public == 1) + elsif (attachment.container.has_attribute?(:course) ||attachment.container.has_attribute?(:course_id) ) && attachment.container.course + course = attachment.container.course + candown = User.current.member_of_course?(course) || (attachment.is_public == 1) || attachment.get_status_by_attach(User.current.id) == 2 + elsif attachment.container.is_a?(Course) + course = attachment.container + candown= User.current.member_of_course?(course) || (attachment.is_public == 1) || attachment.get_status_by_attach(User.current.id) == 2 + elsif attachment.container.is_a?(OrgSubfield) + org = attachment.container.organization + candown = User.current.member_of_org?(org) || ((attachment.is_public == 1 || attachment.get_status_by_attach(User.current.id) == 2) && org.allow_guest_download == true) + elsif attachment.container.is_a?(OrgDocumentComment) + org = attachment.container.organization + candown = org.allow_guest_download || User.current.member_of_org?(org) || (org.is_public && attachment.is_public == 1) + elsif (attachment.container.has_attribute?(:board) || attachment.container.has_attribute?(:board_id)) && attachment.container.board && + attachment.container.board.course + course = attachment.container.board.course + candown= User.current.member_of_course?(course) || (course.is_public==1 && attachment.is_public == 1) + elsif attachment.container.class.to_s=="Organization" + candown = true + elsif attachment.container.class.to_s=="HomeworkAttach" + candown = true + elsif attachment.container.class.to_s=="StudentWorksScore" + candown = true + elsif attachment.container.class.to_s=="StudentWork" + candown = true + elsif attachment.container.class.to_s=="Contest" + candown = true + elsif attachment.container.class.to_s=="Work" + candown = true + elsif attachment.container.class.to_s=="ContestantWork" + candown = true + elsif attachment.container.class.to_s=="HomeworkBank" + candown = true + elsif attachment.container.class.to_s=="BlogComment" #博客资源允许下载 + candown = true + elsif attachment.container.class.to_s=="Memo" #论坛资源允许下载 + candown = true + elsif attachment.container.class.to_s=="Syllabus" #论坛资源允许下载 + candown = true + elsif attachment.container.class.to_s=="Competition" #竞赛资源允许下载 + candown = true + elsif attachment.container.class.to_s=="Career" #职业路径资源允许下载 + candown = true + elsif attachment.container_type == "Inform" #竞赛通知公告允许下载 + candown = true + elsif attachment.container.class.to_s == "User" + candown = (attachment.is_public == 1 || attachment.is_public == true || attachment.author_id == User.current.id) + elsif attachment.container_type == "Bid" && attachment.container && attachment.container.courses + course = attachment.container.courses.first + candown = User.current.member_of_course?(attachment.container.courses.first) || (course.is_public == 1 && attachment.is_public == 1) + else + candown = (attachment.is_public == 1 || attachment.is_public == true) + end + else + if attachment.container_type == "MarkDown" || attachment.container_type.nil? || attachment.container_type == 'Subject' || attachment.container_type == "Shixun" || attachment.container_type == "Memo" || attachment.container_type == "Career" || attachment.container_type == "Exercise" || attachment.container_type == "ExerciseBank" + candown = true + end + end + candown + end + + def project_type_link(text, value) + if value == 1 + link_to "#{text}".html_safe,"javascript:void(0)" ,:onClick => "show_window();", :class => "pr_join_a",:id => "setting_project_type" + elsif value == 2 + link_to "#{text}".html_safe,"javascript:void(0)" ,:onClick => "show_window();", :class => "pr_join_a",:id => "setting_project_type" + else + link_to "#{text}".html_safe,"javascript:void(0)" ,:onClick => "show_window();", :class => "pr_join_a",:id => "setting_project_type" + end + + end + + #如果学生作品被打分后修改,应该给老师提示 + def send_message_to_teacher student_work + if StudentWork === student_work + student_work_scores = student_work.student_works_scores.where("reviewer_role != 3") + if student_work_scores.any? + student_work.update_column('re_commit', 1) + course = student_work.homework_common.course + course.teachers.where(:user_id => student_work_scores.map(&:user_id).uniq).each do|mem| + student_work.tidings << Tiding.new(:user_id => mem.user_id, :trigger_user_id => student_work.user_id, :container_id => student_work.id, :container_type => "StudentWork", :parent_container_id => student_work.homework_common_id, :parent_container_type => "HomeworkCommon", + :belong_container_id => course.id, :belong_container_type => "Course", :viewed => 0, :tiding_type => "HomeworkCommon", :extra => "resubmit") + end + end + end + end + + private + + def wiki_helper + helper = Redmine::WikiFormatting.helper_for(Setting.text_formatting) + extend helper + return self + end + + def link_to_content_update(text, url_params = {}, html_options = {}) + link_to(text, url_params, html_options) + end + +#added by nie +# Display watcher picture + def show_more_watchers?(obj) + if User.watched_by(obj.id).count > 6 + return true + else + return false + end + end + + def show_watcher_profile(obj) + count = 0 + html = '' + if User.watched_by(obj.id).count == 0 + html << (content_tag "span", l(:label_no_current_watchers)) + end + for user in User.watched_by(obj.id) + html << (link_to image_tag(url_to_avatar(user), :class => "avatar"), user_path(user), :class => "avatar", :title => "#{user.name}") + count = count + 1 + if count >= 12 + break + end + end + html.html_safe + end + +#display bid project + def show_more_bid_project?(bid) + if bid.projects.where('is_public = 1').count > 12 + return true + else + return false + end + end + + def show_bid_project(bid) + html = '' + if bid.projects.where('is_public = 1').count == 0 + html << (content_tag "p", l(:label_no_bid_project), :class => "font_lighter") + else + bid.projects.where('is_public = 1').take(12).each do |project| + html << (link_to image_tag(url_to_avatar(project), :class => "avatar", :title => project.name), project_path(project), :class => "avatar") + end + end + html.html_safe + end + + def show_bid_fans_picture(obj) + html = '' + if obj.watcher_users.count == 0 + html << (content_tag "span", l(:label_project_no_follow)) + else + obj.watcher_users.take(12).each do |user| + html << (link_to image_tag(url_to_avatar(user), :class => "avatar"), user_path(user), :class => "avatar", :title => user.name) + end + end + html.html_safe + end + +#display contest project + def show_more_contest_project?(contest) + if contest.projects.where('is_public = 1').count > 12 + return true + else + return false + end + end + + def show_more_contest_softapplication?(contest) + if contest.softapplications.where('is_public = 1').count > 12 + return true + else + return false + end + end + + def show_contest_project(bid) + html = '' + if contest.projects.where('is_public = 1').count == 0 + html << (content_tag "p", l(:label_no_bid_project), :class => "font_lighter") + else + contest.projects.where('is_public = 1').take(12).each do |project| + html << (link_to image_tag(url_to_avatar(project), :class => "avatar", :title => project.name), project_path(project), :class => "avatar") + end + end + html.html_safe + end + + def show_contest_project(contest) + html = '' + if contest.projects.where('is_public = 1').count == 0 + html << (content_tag "p", l(:label_no_bid_project), :class => "font_lighter") + else + contest.projects.where('is_public = 1').take(12).each do |project| + html << (link_to image_tag(url_to_avatar(project), :class => "avatar", :title => project.name), project_path(project), :class => "avatar") + end + end + html.html_safe + end + + def show_contest_softapplication(contest) + html = '' + if contest.softapplications.where('is_public = 1').count == 0 + html << (content_tag "p", l(:label_no_contest_softapplication), :class => "font_lighter") + else + contest.softapplications.where('is_public = 1').take(12).each do |softapplication| + html << (link_to image_tag(url_to_avatar(project), :class => "avatar", :title => project.name), project_path(project), :class => "avatar") + end + end + html.html_safe + end + + def show_contest_fans_picture(obj) + html = '' + if obj.watcher_users.count == 0 + html << (content_tag "span", l(:label_project_no_follow)) + else + obj.watcher_users.take(12).each do |user| + html << (link_to image_tag(url_to_avatar(user), :class => "avatar"), user_path(user), :class => "avatar", :title => user.name) + end + end + html.html_safe + end + +#display fans picture + def show_more_fans?(obj) + if obj.watcher_users.count > 12 + return true + else + return false + end + end + + def show_fans_picture(obj) + html = '' + if obj.watcher_users.count == 0 + html << (content_tag "span", l(:label_no_current_fans)) + else + obj.watcher_users.take(12).each do |user| + html << (link_to image_tag(url_to_avatar(user), :class => "avatar"), user_path(user), :class => "avatar", :title => user.name) + end + end + html.html_safe + end + + # added by bai + def show_more_participate?(obj) + if obj.join_in_contests.count > 12 + return true + else + return false + end + end + + def show_participate_picture(obj) + html = '' + count = 0 + if obj.join_in_contests.count == 0 + html << (content_tag "span", l(:label_no_current_participate)) + end + for temp in obj.join_in_contests + html << (link_to image_tag(url_to_avatar(temp.user), :class => "avatar"), user_path(temp.user), :class => "avatar", :title => "#{temp.user.name}") + count = count + 1 + if count >= 12 + break + end + end + html.html_safe + end + +#end + +# add by huang + def show_watcher_list(user) + html = '' + count = 0 + for user in User.watched_by(user.id) + html << (link_to image_tag(url_to_avatar(user), :class => "avatar"), user_path(user), :class => "avatar", :title => "#{user.name}") + count = count + 1 + if count >= 12 + break + end + end + html.html_safe + end +# end + +#added by william + def get_fans_num(user) + user.watcher_users.count + end +#end + + + def hadcommittedhomework(cur,curb) + bid = Bid.find_by_id(curb) + return true if bid.nil? + + case bid.homework_type + when Bid::HomeworkFile + attaches = HomeworkAttach.where(bid_id: curb) + attaches.map(&:user_id).include? cur + when Bid::HomeworkProject + attaches = BidingProject.where(user_id: User.current, bid_id: bid) + attaches.count > 0 # > 0 则有提交记录 + else + true + end + + end + + def render_dynamic_nav + home_link = link_to l(:field_homepage), {:controller => 'welcome', :action => 'index'} + home_link = "
  • " << home_link << "
  • " + # bootstrap_render_dynamic_nav + content_tag :ul, (home_link.html_safe+bootstrap_render_dynamic_nav) + end + + def bootstrap_render_dynamic_nav + hidden_non_project = Setting.find_by_name("hidden_non_project") + visiable = !(hidden_non_project && hidden_non_project.value == "0") + + main_course_link = link_to l(:label_course_practice), {:controller => 'welcome', :action => 'index', :host => Setting.host_course} + main_project_link = link_to l(:label_project_deposit), {:controller => 'welcome', :action => 'index', :host => Setting.host_name} + main_contest_link = link_to l(:label_contest_innovate), {:controller => 'welcome', :action => 'index', :host => Setting.host_contest} + + # course_all_course_link = link_to l(:label_course_all), {:controller => 'courses', :action => 'index'} + course_teacher_all_link = link_to l(:label_teacher_all), {:controller => 'users', :action => 'index', :role => 'teacher', :host => Setting.host_course} + # courses_link = link_to l(:label_course_practice), {:controller => 'courses', :action => 'index'} + #users_link = link_to l(:label_software_user), {:controller => 'users', :action => 'index', :host => Setting.host_user} + # contest_link = link_to l(:label_contest_innovate), {:controller => 'contests', :action => 'index'} + # bids_link = link_to l(:label_requirement_enterprise), {:controller => 'bids', :action => 'index'} + forum_link = link_to l(:label_forum_all), {:controller => "forums", :action => "index"} + stores_link = link_to l(:label_stores_index), {:controller => 'stores', :action=> 'index'} + school_all_school_link = link_to l(:label_school_all), {:controller => 'school', :action => 'index'} + project_new_link = link_to l(:label_project_new), {:controller => 'projects', :action => 'new', :host => Setting.host_name} + # project_mine_link = link_to l(:label_my_project), {:controller => 'users', :action => 'user_projects', :host => Setting.host_name} + + #@nav_dispaly_project_label + nav_list = Array.new + nav_list.push(school_all_school_link) if @nav_dispaly_course_all_label && @show_course == 1 && visiable + # nav_list.push(course_all_course_link) if @nav_dispaly_course_all_label && @show_course == 1 + nav_list.push(course_teacher_all_link) if @nav_dispaly_teacher_all_label && @show_course == 1 && visiable + + nav_list.push(main_project_link) if @nav_dispaly_main_project_label + nav_list.push(main_course_link) if @nav_dispaly_main_course_label && @show_course == 1 && visiable + nav_list.push(main_contest_link) if @nav_dispaly_main_contest_label && @show_contest == 1 && visiable + + nav_list.push(courses_link) if @nav_dispaly_course_label && @show_course == 1 && visiable + nav_list.push(project_new_link) if @nav_dispaly_project_label + # nav_list.push(project_mine_link) if @nav_dispaly_main_project_label + # nav_list.push(projects_link) if @nav_dispaly_project_label + #nav_list.push(users_link) if @nav_dispaly_user_label + # nav_list.push(contest_link) if @nav_dispaly_contest_label && @show_contest == 1 + nav_list.push(bids_link) if @nav_dispaly_bid_label && visiable + nav_list.push(forum_link) if @nav_dispaly_forum_label && visiable + nav_list.push(stores_link) if @nav_dispaly_store_all_label && visiable + + content_li = '' + nav_list.collect do |nav_item| + content_li << content_tag(:li, nav_item, :class => 'topnav_a fl') + end + content_li.html_safe + end + + def current_user + User.current + end + + # def hadcommittedforcontest(curu) + # message = JournalsForMessage.find_by_sql("select * from journals_for_messages where jour_type = 'Softapplication' ") + # message.each do |createmessage| + # if createmessage.user_id == curu + # return true + # end + # end + # end + + # 获取用户的认证状态 + def get_authentication_status user + result = '' + if user.authentication + result += '
  • ' + else + apply_auth = ApplyUserAuthentication.where(:user_id => user.id, :auth_type => 1).last + if apply_auth && apply_auth.status == 0 + result += '
  • ' + else + result += '
  • ' + end + end + if user.professional_certification + result += '
  • ' + else + apply_auth = ApplyUserAuthentication.where(:user_id => user.id, :auth_type => 2).last + if apply_auth && apply_auth.status == 0 + result += '
  • ' + else + result += '
  • ' + end + end + return result.html_safe + end + + def footer_logo(ul_class=nil, li_class=nil) + logos = [] + logos.push(link_to image_tag('/images/footer_logo/nudt.png',:alt=>"nudt"),"http://www.nudt.edu.cn/special.asp?classid=12" ) + logos.push(link_to image_tag('/images/footer_logo/peking_eecs.png', :alt=>"peking_eecs"), "http://www.sei.pku.edu.cn/" ) + logos.push(link_to image_tag('/images/footer_logo/buaa_scse.png', :alt=>"buaa_scse"), "http://scse.buaa.edu.cn/" ) + logos.push(link_to image_tag('/images/footer_logo/iscas.png', :alt=>"iscas"), "http://www.iscas.ac.cn" ) + logos.push(link_to image_tag('/images/footer_logo/inforbus.png', :alt=>"inforbus"), "http://www.inforbus.com" ) + + logos.collect! { |logo| + content_tag(:li, logo.html_safe, :class => li_class.to_s) + } + + content_tag(:ul, logos.join("").html_safe, :class => ul_class.to_s).html_safe + end + + def sort_homework_path(bid, sort, direction) + case self.action_name + when 'show_courseEx' + get_not_batch_homework_homework_attach_index_path(bid_id: bid.id, sort: sort, direction: 'asc') + when 'get_not_batch_homework' + get_not_batch_homework_homework_attach_index_path(bid_id: bid.id, sort: sort, direction: direction) + when 'get_batch_homeworks' + get_batch_homeworks_homework_attach_index_path(bid_id: bid.id, sort: sort, direction: direction) + when 'get_homeworks' + get_homeworks_homework_attach_index_path(bid_id: bid.id, sort: sort, direction: direction) + else + '#' + end + end + + def anonymous_comment_link(bid, course) + link = case bid.comment_status + when 0 + confirm_info = "开启匿评后学生将不能对作品进行提交、修改、删除等操作\n" + confirm_info += anonymous_comment_notice(bid,course) + confirm_info += '是否确定开启匿评?' + link_to '启动匿评', start_anonymous_comment_bid_path(bid), id: "#{bid.id}_start_anonymous_comment", remote: true, :confirm => confirm_info, disable_with: '加载中...' + when 1 + confirm_info = "关闭匿评后所有同学将不能继续进行匿评,且将公开已提交作品列表\n" + confirm_info += anonymous_comment_notice(bid,course) + confirm_info += '是否确定关闭匿评?' + link_to '关闭匿评', stop_anonymous_comment_bid_path(bid), id: "#{bid.id}_stop_anonymous_comment", remote: true, :confirm => confirm_info + when 2 + '匿评结束' + end + content_tag('span', link, id: "#{bid.id}_anonymous_comment") + end + + def anonymous_comment_notice(bid, course) + case bid.comment_status + when 0 + @student_size ||= searchStudent(course).size + @homework_size = bid.homeworks.size + percent = @homework_size.to_f / (@student_size == 0 ? 1 : @student_size) + confirm_info = "目前#{@student_size}个学生,总共提交了#{@homework_size}份作品,占#{number_to_percentage(percent * 100, precision: 1)}\n" + when 1 + @homework_evaluations = 0 + bid.homeworks.map { |homework| @homework_evaluations += homework.homework_evaluations.count} + teachers = "(" + teacher_members = searchTeacherAndAssistant(course) + teacher_members.each do |member| + if member == teacher_members.last + teachers += member.user_id.to_s + ")" + else + teachers += member.user_id.to_s + "," + end + end + @has_evaluations = 0 + bid.homeworks.map { |homework| @has_evaluations += homework.rates(:quality).where("seems_rateable_rates.rater_id not in #{teachers}").count} + + percent = @has_evaluations.to_f / (@homework_evaluations == 0 ? 1 : @homework_evaluations) + confirm_info = "目前总共分配了#{@homework_evaluations}份匿评作品,已评价#{@has_evaluations}份作品,占#{number_to_percentage(percent * 100, precision: 1)}\n" + end + confirm_info + end + + def get_technical_title user + if user.user_extensions.technical_title == "Professor" || user.user_extensions.technical_title == "教授" + technical_title = l(:label_technicl_title_professor) + elsif user.user_extensions.technical_title == "Associate professor" || user.user_extensions.technical_title == "副教授" + technical_title = l(:label_technicl_title_associate_professor) + elsif user.user_extensions.technical_title == "Lecturer" || user.user_extensions.technical_title == "讲师" + technical_title = l(:label_technicl_title_lecturer) + elsif user.user_extensions.technical_title == "Teaching assistant" || user.user_extensions.technical_title == "助教" + technical_title = l(:label_technicl_title_teaching_assistant) + end + technical_title + end + + # 用户竞赛总数 + def user_contest_count + @user.favorite_contests.visible.where("is_delete =?", 0).count + end + + # 用户项目总数 + def user_project_count + @my_projects = @user.projects.visible.where("status != 9") + @my_project_total = @my_projects.count + end + + # 用户的课程总数 + def user_course_count + @my_course_count = @user.syllabuses.count + + sy_courses = @user.courses.visible.not_deleted + syllabus_ids = sy_courses.empty? ? '(-1)' : "(" + sy_courses.map{|course| !course.syllabus_id.nil? && course.syllabus_id}.join(",") + ")" + syllabus_members = SyllabusMember.where("user_id = #{@user.id}") + syllabus_member_ids = syllabus_members.empty? ? "(-1)" : "(" + syllabus_members.map{|syl_mem| syl_mem.syllabus_id}.join(',') + ")" + @join_syllabuses = Syllabus.where("(id in #{syllabus_ids} or id in #{syllabus_member_ids}) and user_id != #{@user.id}") + @my_joined_course_count = @join_syllabuses.count + + @user_course_total = @my_joined_course_count + @my_course_count + end + + # 用户发布的作业数 + def user_manage_homework_count + tea_courses = @user.courses.visible.not_deleted.select{|course| @user.has_teacher_role(course)} + tea_course_ids = tea_courses.map{|course| course.id} + @manage_homeworks = HomeworkCommon.where(:course_id => tea_course_ids).count + end + + # 用户收到的作业数 + def user_receive_homework_count + stu_courses = @user.courses.visible.not_deleted.select{|course| @user.has_student_role(course)} + stu_course_ids = stu_courses.empty? ? "(-1)" : "(" + stu_courses.map{|course| course.id}.join(',') + ")" + @homeworks = HomeworkCommon.where("course_id in #{stu_course_ids} and publish_time <= '#{Time.now}'").count + end + + # 用户发布的issue数 + def issues_author_is_self_count + Issue.where(:author_id => @user.id).count + end + + # 用户收到的issue数 + def issues_assigned_is_self_count + Issue.where( :assigned_to_id => @user.id ).count + end + + def get_user_roll user + technical_title = "" + case user.user_extensions.identity.to_s + when "0" + technical_title = get_technical_title user + when "1" + technical_title = l(:label_account_identity_student) + when "2" + technical_title = l(:label_account_identity_enterprise) + when "3" + technical_title = l(:label_account_identity_developer) + end + technical_title + end + + + def ie8? + request.env["HTTP_USER_AGENT"] =~ /MSIE 8.0/ + end + + + #获取指定资源列表的TAG的集合以及每个TAG的数量,降序排序 + def attachment_tag_list attachments + tag_list = Hash.new + attachments.each do |attachment| + attachment.tag_list.map{|tag| tag_list.has_key?(tag) ? tag_list[tag] = tag_list[tag] + 1 : tag_list[tag] = 1} + end + tag_list.sort {|a,b| b[1]<=>a[1]} + end + + #获取课程资源的TAG云 + def get_course_tag_list course + all_attachments = course.attachments + if User.current.admin? || User.current.allowed_to?(:as_teacher, course) + all_attachments = all_attachments.reorder("created_on desc") + elsif User.current.member_of_course?(course) + member = course.members.where(:user_id => User.current.id).first + if member.try(:course_group_id).to_i == 0 + all_attachments = all_attachments.where("is_publish = 1 and unified_setting = 1") + else + not_atta_ids = course.attachment_group_settings.where("course_group_id = #{member.try(:course_group_id)} and publish_time > '#{Time.now}'") + not_atta_ids = not_atta_ids.blank? ? "(-1)" : "(" + not_atta_ids.map(&:attachment_id).join(",") + ")" + all_attachments = all_attachments.where("is_publish = 1 and attachments.id not in #{not_atta_ids}") + end + else + all_attachments = all_attachments.where("is_publish = 1 and unified_setting = 1") + end + tag_list = attachment_tag_list all_attachments + tag_list + end + + # 获取项目资源的Tag云 + def get_project_tag_list project + all_attachments = project.attachments.select{|attachment| attachment.is_public? || + (attachment.container_type == "Project" && User.current.member_of?(project))|| + attachment.author_id == User.current.id + } + tag_list = attachment_tag_list all_attachments + tag_list + end + + # 获取项目fork成员数 + def project_fork_count + @forked_projects = Project.where(:forked_from_project_id => @project.id) + @forked_count = @forked_projects.count + end + + def get_org_subfield_tag_list org_subfield + all_attachments = org_subfield.attachments.select{|attachment| attachment.is_public? || + (attachment.container_type == "OrgSubfield" && User.current.member_of_org?(org_subfield.organization))|| + attachment.author_id == User.current.id + } + tag_list = attachment_tag_list all_attachments + tag_list + end + + #获取匿评相关连接代码 + def homework_anonymous_comment (homework, hw_status, user_activity_id = -1) + if homework.homework_detail_manual.comment_status == 0 || homework.end_time >= Time.now + link = link_to "启动匿评","javascript:void(0)", :class => "wpostOptionLink", :title => "作业截止日期之前不可以启动匿评" + elsif homework.student_works.has_committed.count >= 2 && homework.homework_detail_manual#作业份数大于2 + case homework.homework_detail_manual.comment_status + when 1 + link = link_to '启动匿评', Setting.protocol + "://" + Setting.host_name + "/homework_common/" + homework.id.to_s + "/alert_anonymous_comment?hw_status=" + hw_status.to_s + "&user_activity_id=" + user_activity_id.to_s, id: "#{homework.id}_start_anonymous_comment", remote: true, disable_with: '加载中...',:class => 'wpostOptionLink' + when 2 + link = link_to '关闭匿评', Setting.protocol + "://" + Setting.host_name + "/homework_common/" + homework.id.to_s + "/alert_anonymous_comment?hw_status=" + hw_status.to_s + "&user_activity_id=" + user_activity_id.to_s, id: "#{homework.id}_stop_anonymous_comment", remote: true,:class => 'wpostOptionLink' + when 3 + # link = link_to "匿评结束","javascript:void(0)", :class => "postOptionLink", :title => "匿评结束" + end + else + link = link_to "启动匿评","javascript:void(0)", :class => "wpostOptionLink", :title => "学生提交作业数大于等于2时才可以启动匿评" + end + link + end + #学生根据传入作业确定显示为编辑作品还是新建作品 + def student_new_homework homework + work = cur_user_works_for_homework homework + if work.nil? + link_to "提交作品", new_student_work_path(:homework => homework.id),:class => 'fr mr10 work_edit' + else + if homework.homework_type == 1 && homework.homework_detail_manual && homework.homework_detail_manual.comment_status != 1 #匿评作业,且作业状态不是在开启匿评之前 + link_to "作品已交", "javascript:void(0);", :class => 'fr mr10 pr_join_span c_white', :title => "开启匿评后不可修改作品" + elsif homework.homework_type == 2 #编程作业修改作品 + if homework.homework_detail_manual && homework.homework_detail_manual.comment_status != 1 + link_to "作品已交", "javascript:void(0);", :class => 'fr mr10 pr_join_span c_white', :title => "开启匿评后不可修改作品" + else + link_to "修改作品", new_student_work_path(:homework => homework.id),:class => 'fr mr10 work_edit' + end + else + link_to "修改作品", edit_student_work_path(work.id),:class => 'fr mr10 work_edit' + end + end + end + #动态列表中,确定学生是该提交还是进列表 + def student_work_activity_submit_status(opt={}) + default_opt = {class: 'c_blue'}.merge(opt) + + is_teacher = User.current.user_extensions && User.current.user_extensions.identity == 0 && User.current.allowed_to?(:add_course, nil, :global => true) + + homework = default_opt[:homework] + work = cur_user_works_for_homework homework + if work.nil? && !is_teacher + link_to "提交("+homework.student_works.count.to_s+")", new_student_work_path(:homework => homework.id,:host=> Setting.host_course), :class=> default_opt[:class] + else + link_to "提交("+homework.student_works.count.to_s+")", student_work_index_path(:homework => homework.id,:host=> Setting.host_course), :class=> default_opt[:class] + end + end + + # 试卷动态的按钮 + def user_for_exercise exercise,is_teacher + count = exercise.exercise_users.where(:commit_status => 1, :user_id => exercise.course.student.map(&:student_id)).count + if User.current.logged? + if User.current.member_of_course?(exercise.course) + if is_teacher #老师显示作品数量 + link_to "作品 (#{count})".html_safe, student_exercise_list_exercise_path(exercise), :class => "c_blue homepagePostSubmit" + else #学生显示提交作品、修改作品等按钮 + work = exercise.exercise_users.where("user_id = ?",User.current).first + member = exercise.course.members.where(:user_id => User.current.id).first + setting_time = exercise_group_setting exercise, member.try(:course_group) + if work + if work.commit_status > 0 + link_to "查看答题(#{count})", exercise.exercise_status < 3 ? exercise_path(exercise,:user_id => User.current.id) : show_student_result_exercise_path(exercise,:user_id => User.current.id), :class => "c_blue homepagePostSubmit" + else + if setting_time.publish_time < Time.now && setting_time.end_time > Time.now + link_to (work.start_at.nil? ? "开始答题(#{count})" : "继续答题(#{count})"), exercise_path(exercise,:user_id => User.current.id), :class => "c_blue homepagePostSubmit" + else + link_to "查看作品(#{count})".html_safe, student_exercise_list_exercise_path(exercise), :class => "c_blue homepagePostSubmit" + end + end + else + if setting_time.publish_time < Time.now && setting_time.end_time > Time.now + link_to "开始答题(#{count})", exercise_path(exercise,:user_id => User.current.id), :class => "c_blue homepagePostSubmit" + else + link_to "查看作品(#{count})".html_safe, student_exercise_list_exercise_path(exercise), :class => "c_blue homepagePostSubmit" + end + end + end + else + link_to "作品 (#{count})".html_safe, "javascript:void(0)", :class => "c_blue homepagePostSubmit", :onclick => "notice_sure_box('您不是班级成员,不能答题
    请先从老师处获取邀请码后加入班级,再答题')" + end + else + link_to "作品 (#{count})".html_safe, "javascript:void(0)", :class => "c_blue homepagePostSubmit", :onclick => "login_notice_box('#{signin_url_without_domain}');" + end + end + + # 问卷动态的按钮 + def user_for_poll poll,is_teacher + count = poll.poll_users.where(:commit_status => 1, :user_id => poll.course.student.map(&:student_id)).count + if User.current.logged? + if User.current.member_of_course?(poll.course) + if is_teacher #老师显示作品数量 + link_to "作品 (#{count})".html_safe, student_poll_list_poll_path(poll), :class => "c_blue homepagePostSubmit" + else #学生显示提交作品、修改作品等按钮 + work = poll.poll_users.where("user_id = ?",User.current).first + member = poll.course.members.where(:user_id => User.current.id).first + setting_time = poll_group_setting poll, member.try(:course_group) + if work + if work.commit_status > 0 + link_to "查看答题(#{count})", poll_path(poll,:user_id => User.current.id), :class => "c_blue homepagePostSubmit" + elsif setting_time.publish_time < Time.now && setting_time.end_time > Time.now + link_to (work.start_at.nil? ? "开始答题(#{count})" : "继续答题(#{count})"), poll_path(poll,:user_id => User.current.id), :class => "c_blue homepagePostSubmit" + else + link_to "查看作品(#{count})".html_safe, student_poll_list_poll_path(poll), :class => "c_blue homepagePostSubmit" + end + else + if setting_time.publish_time < Time.now && setting_time.end_time > Time.now + link_to "开始答题(#{count})", poll_path(poll,:user_id => User.current.id), :class => "c_blue homepagePostSubmit" + else + link_to "查看作品(#{count})".html_safe, student_poll_list_poll_path(poll), :class => "c_blue homepagePostSubmit" + end + end + end + else + link_to "作品 (#{count})".html_safe, "javascript:void(0)", :class => "c_blue homepagePostSubmit", :onclick => "notice_sure_box('您不是班级成员,不能答题
    请先从老师处获取邀请码后加入班级,再答题')" + end + else + link_to "作品 (#{count})".html_safe, "javascript:void(0)", :class => "c_blue homepagePostSubmit", :onclick => "login_notice_box('#{signin_url_without_domain}');" + end + end + + #根据传入作业确定显示为编辑作品还是新建作品,或者显示作品数量 + def user_for_homework_common homework,work + if User.current.logged? + project = cur_user_projects_for_homework homework if homework.homework_type == 3 + member = homework.course.members.where(:user_id => User.current.id).first + setting_time = homework_group_setting homework, member.try(:course_group_id) + if homework.homework_type == 4 + if work.nil? + link_to "开始实战", shixun_path(homework.homework_commons_shixuns.shixun), :class => 'edu-default-btn user_bluebg_btn fr mr20 pl7 pr7',:target => "_blank" + else + myshixun = Myshixun.where(:id => work.myshixun_id).first + # is_modify = ShixunModify.where(:myshixun_id => myshixun.try(:id), :shixun_id => myshixun.shixun.try(:id), :status => 1).first + link_to "继续实战", shixun_path(myshixun.shixun), :class => "edu-default-btn user_orangebg_btn fr mr20 pl7 pr7", :target => "_blank" + # if myshixun && is_modify.blank? + # link_to "继续实战", myshixun_game_path(myshixun.current_task, :myshixun_id => myshixun), :class => "edu-default-btn user_orangebg_btn fr mr20 pl7 pr7", :target => "_blank" + # elsif myshixun + # link_to "继续实战", 'javascript:void(0);', :onclick => "sure_box_redirect('#{myshixun_reset_myshixun_path(myshixun)}', '实训已经更新啦,系统正在为您重置');", :class => "edu-default-btn user_orangebg_btn fr mr20 pl7 pr7" + # end + end + elsif work.nil? && setting_time.end_time >= Time.now + if homework.homework_type ==3 && project.nil? && homework.homework_detail_group.base_on_project == 1 + link_to "提交作品", "javascript:void(0)", :class => 'edu-default-btn user_bluebg_btn fr mr20 pl7 pr7',:style=>"cursor:not-allowed",:title => '请先关联项目再提交作品' + else + link_to "提交作品", new_student_work_url_without_domain(homework.id),:class => 'edu-default-btn user_bluebg_btn fr mr20 pl7 pr7' + end + elsif work.nil? && setting_time.end_time < Time.now + if homework.allow_late && !homework.course.is_end + if homework.homework_type ==3 && project.nil? && homework.homework_detail_group.base_on_project == 1 + link_to "补交作品", "javascript:void(0)", :class => 'edu-default-btn user_orangebg_btn fr mr20 pl7 pr7',:style=>"cursor:not-allowed",:title => '请先关联项目再补交作品' + else + link_to "补交作品", new_student_work_url_without_domain(homework.id),:class => 'edu-default-btn user_orangebg_btn fr mr20 pl7 pr7' + end + end + elsif work + work_ids = "(" + homework.student_works.has_committed.map(&:id).join(",") + ")" + if homework.homework_detail_manual && homework.homework_detail_manual.comment_status == 3 && User.current.student_works_evaluation_distributions.where("student_work_id IN #{work_ids}").count > 0 #匿评作业,且作业状态不是在开启匿评之前 + link_to "作品匿评", student_work_index_path(:homework => homework.id), :class => 'edu-default-btn user_orangebg_btn fr mr20 pl7 pr7', :title => "开启匿评后不可修改作品" + elsif homework.homework_detail_manual && homework.homework_detail_manual.comment_status > 3 + link_to "查看作品",student_work_path(work), :class => 'edu-default-btn user_greybg_btn fr mr20 pl7 pr7', :title => "匿评已结束" + elsif setting_time.end_time >= Time.now && work.user_id == User.current.id + link_to "修改作品", edit_student_work_url_without_domain(work.id),:class => 'edu-default-btn user_orangebg_btn fr mr20 pl7 pr7' + else + link_to "查看作品", student_work_path(work), :class => 'edu-default-btn user_greybg_btn fr mr20 pl7 pr7', :title => "作业截止后不可修改作品" + end + end + else + link_to "作品".html_safe, "javascript:void(0)", :class => "edu-default-btn user_greybg_btn fr mr20 pl7 pr7", :onclick => "login_notice_box('#{signin_url_without_domain}');" + end + end + + #根据传入作业确定显示为编辑作品还是新建作品,或者显示作品数量 + def user_for_contest_work homework,is_contestant,work + count = homework.contestant_works.has_committed.count + if User.current.logged? + if User.current.member_of_contest?(homework.contest) || User.current.admin? + if !is_contestant #老师显示作品数量 + link_to "作品(#{count})", contestant_works_path(:work =>homework.id, :tab => 2), :class => "c_blue" + else #学生显示提交作品、修改作品等按钮 + work = cur_user_works_for_work homework + project = cur_user_projects_for_work homework + if work.nil? && homework.work_status == 1 + if homework.work_type ==3 && project.nil? && homework.work_detail_group.base_on_project + link_to "提交作品(#{count})","javascript:void(0)", :class => 'c_grey',:style=>"cursor:not-allowed",:title => '请先关联项目再提交作品' + else + link_to "提交作品(#{count})", new_contestant_work_path(:work => homework.id),:class => 'c_blue' + end + elsif work.nil? && homework.work_status > 1 + if homework.work_type ==3 && project.nil? && homework.work_detail_group.base_on_project + link_to "补交作品(#{count})","javascript:void(0)", :class => 'c_grey',:style=>"cursor:not-allowed",:title => '请先关联项目再补交作品' + else + link_to "补交作品(#{count})", new_contestant_work_path(:work => homework.id),:class => 'c_blue' + end + else + if homework.work_status == 1 && work.user_id == User.current.id + link_to "修改作品(#{count})", edit_contestant_work_path(work.id),:class => 'c_blue' + else + link_to "查看作品(#{count})", contestant_works_path(:work =>homework.id, :tab => 2), :class => 'c_blue', :title => "不可修改作品" + end + end + end + else + link_to "作品(#{count})", "javascript:void(0)", :class => "c_blue", :onclick => "notice_sure_box('您不是参赛者,不能提交作品
    请加入竞赛,待审批通过后再提交作品')" + end + else + link_to "作品(#{count})", "javascript:void(0)", :class => "c_blue", :onclick => "login_notice_box('#{signin_url_without_domain}');" + end + end + + #根据传入作业确定显示为提交作品、补交作品、查看作品等 + def student_for_homework_common homework + if User.current.allowed_to?(:as_teacher, homework.course) + link_to "查看作品", student_work_index_url_in_org(homework.id, 2), :class => 'hw_btn_green fr mt5', :title => "查看作品", :target => '_blank' + else User.current.member_of_course?(homework.course) + work = cur_user_works_for_homework homework + project = cur_user_projects_for_homework homework + if work.nil? && homework.end_time >= Time.now + if homework.homework_type ==3 && project.nil? && homework.homework_detail_group.base_on_project == 1 + link_to "关联项目", student_work_index_url_in_org(homework.id, 1), :class => 'hw_btn_green fr mt5',:title => '查看分组作业详情', :target => '_blank' + else + link_to "提交作品", new_student_work_url_without_domain(homework.id),:class => 'hw_btn_green fr mt5', :target => '_blank' + end + elsif work.nil? && homework.end_time < Time.now + if homework.homework_type ==3 && project.nil? && homework.homework_detail_group.base_on_project == 1 + link_to "关联项目", student_work_index_url_in_org(homework.id, 1), :class => 'hw_btn_green fr mt5',:title => '查看分组作业详情', :target => '_blank' + else + link_to "补交作品", new_student_work_url_without_domain(homework.id),:class => 'btn_orange_big fr mt5', :target => '_blank' + end + else + if homework.homework_detail_manual && homework.homework_detail_manual.comment_status == 2 #匿评作业,且作业状态不是在开启匿评之前 + link_to "作品匿评", student_work_index_url_in_org(homework.id, 2), :class => 'hw_btn_green fr mt5', :title => "开启匿评后不可修改作品", :target => '_blank' + elsif homework.homework_detail_manual && homework.homework_detail_manual.comment_status == 3 + link_to "查看作品",student_work_index_url_in_org(homework.id, 2), :class => 'hw_btn_green fr mt5', :title => "匿评已结束", :target => '_blank' + elsif homework.homework_type == 2 && homework.end_time >= Time.now#编程作业不能修改作品 + link_to "修改作品", new_student_work_url_without_domain(homework.id),:class => 'hw_btn_green fr mt5', :target => '_blank' + elsif homework.end_time >= Time.now && work.user_id == User.current.id + link_to "修改作品", edit_student_work_url_without_domain(work.id),:class => 'hw_btn_green fr mt5', :target => '_blank' + else + link_to "查看作品", student_work_index_url_in_org(homework.id, 2), :class => 'hw_btn_green fr mt5', :title => "作业截止后不可修改作品", :target => '_blank' + end + end + end + end + + def relate_project homework,is_teacher,is_in_course,user_activity_id,course_activity + if User.current.member_of_course?(homework.course) + if is_teacher + #link_to "已关联(#{homework.student_work_projects.count})",student_work_index_path(:homework => homework.id),:class => "c_blue" + else + projects = cur_user_projects_for_homework homework + works = cur_user_works_for_homework homework + if works.nil? && projects.nil? + link_to "关联项目",new_student_work_project_student_work_index_path(:homework => homework.id,:is_in_course=>is_in_course,:user_activity_id=>user_activity_id,:course_activity=>course_activity),remote: true,:class=> 'c_blue', :title=> '请选择分组作业关联的项目' + elsif works.nil? + link_to "取消关联",cancel_relate_project_student_work_index_path(:homework => homework.id,:is_in_course=>is_in_course,:user_activity_id=>user_activity_id,:course_activity=>course_activity), :confirm => "您确定要取消关联吗?", remote: true,:class => "c_blue", :title=> '取消关联项目' + else + #link_to "已关联(#{homework.student_work_projects.count})",student_work_index_path(:homework => homework.id),:class => "c_blue" + end + end + end + end + + def student_anonymous_comment homework + if homework.homework_detail_manual + case homework.homework_detail_manual.comment_status + when 1 + "未开启匿评".html_safe + when 2 + "正在匿评中".html_safe + when 3 + "匿评已结束".html_safe + end + end + end + + #获取当前用户在指定作业下提交的作业的集合 + def cur_user_works_for_homework homework + work = homework.student_works.where("user_id = ? && work_status != 0",User.current).first + # if homework.homework_type == 3 + # pro = homework.student_work_projects.where("user_id = #{User.current.id}").first + # if pro.nil? || pro.student_work_id == "" || pro.student_work_id.nil? + # work = nil + # else + # work = StudentWork.find pro.student_work_id + # end + # end + work + end + #获取当前用户在指定作业下关联的项目的集合 + def cur_user_projects_for_homework homework + homework.student_works.where("user_id = ? and project_id != 0",User.current).first + end + + #获取当前用户在指定题目下提交的作业的集合 + def cur_user_works_for_work homework + work = homework.contestant_works.where("user_id = ? && work_status != 0",User.current).first + if homework.work_type == 3 + pro = homework.contestant_work_projects.where("user_id = #{User.current.id}").first + if pro.nil? || pro.contestant_work_id == "" || pro.contestant_work_id.nil? + work = nil + else + work = ContestantWork.find pro.contestant_work_id + end + end + work + end + #获取当前用户在指定题目下关联的项目的集合 + def cur_user_projects_for_work work + work.contestant_work_projects.where("user_id = ?",User.current).first + end + + #获取当前作业的提交截止时间/互评截止时间 + def cur_homework_end_time homework + str = "" + if homework.anonymous_comment == 0 && homework.end_time && homework.end_time < Time.now && homework.homework_detail_manual + str = "互评截止:#{format_date homework.homework_detail_manual.evaluation_end}" + else + str = "提交截止:#{homework.end_time ? (format_date homework.end_time) : '       --       '}" + end + str + end + + def file_preview_tag(file, html_options={}) + if %w(pdf pptx doc docx xls xlsx).any?{|x| file.filename.downcase.end_with?(x)} + link_to '预览', download_named_attachment_path(file.id, file.filename, preview: true),html_options + end + end + + def file_preview_eye(file, html_options={}) + if %w(pdf pptx doc docx xls xlsx).any?{|x| file.filename.downcase.end_with?(x)} + link_to '', User.current.logged? ? download_named_attachment_path(file.id, file.filename, preview: true) : signin_url_without_domain, html_options + end + end + + #将文本内的/n转换为
    + def text_format text + text.gsub("&","&").gsub("<","<").gsub(">",">").gsub("\n","
    ").html_safe + end + + #评分规则显示 + def scoring_rules late_penalty,homework_id,is_teacher,absence_penalty=nil + if absence_penalty + if late_penalty.to_i == 0 && absence_penalty.to_i == 0 + notice = "尚未设置评分规则" + if is_teacher + notice += ",请 " + link_to("设置",edit_homework_common_path(homework_id),:class => "c_green") + end + elsif late_penalty.to_i != 0 && absence_penalty.to_i == 0 + notice = "迟交扣#{late_penalty}分,缺评扣分未设置" + elsif late_penalty.to_i == 0 && absence_penalty.to_i != 0 + notice = "迟交扣分未设置,缺评一个作品扣#{absence_penalty}分" + elsif late_penalty.to_i != 0 && absence_penalty.to_i != 0 + notice = "迟交扣#{late_penalty}分,缺评一个作品扣#{absence_penalty}分" + end + else + if late_penalty.to_i == 0 + notice = "尚未设置评分规则" + if is_teacher + notice += ",请 " + link_to("设置",edit_homework_common_path(homework_id),:class => "c_green") + end + else + notice = "迟交扣#{late_penalty}分" + end + end + notice.html_safe + end + + #老师C语言的标准代码 + def c_stantard_code_teacher + "// 老师您好!这是一个C语言的样例程序 +// 程序功能:输入两个整数,输出两者之和 +// 测试集合:老师可以给出多组测试集,例如: +// 输入1和2,输出3 +// 输入3和4,输出7 +// ... ... +// 系统将根据您给出的测试集对学生代码进行自动评分 + +// 特别提醒:程序采用命令行传参方式,输入通过argv传入 +// 否则您的作业标准代码将不能通过测试 + +#include //引用必须头文件 +int main(int argc, char** argv) { + int a = atoi(argv[1]); //将第一个输入转成整型 + int b = atoi(argv[2]); //将第二个输入转换为整型 + + printf(\"%d\",a+b); //输出a+b + return 0; +}".html_safe + end + + #老师C++语言的标准代码 + def c_stantard_code_teacher_ + "// 老师您好!这是一个C++语言的样例程序 +// 程序功能:输入两个整数,输出两者之和 +// 测试集合:老师可以给出多组测试集,例如: +// 输入1和2,输出3 +// 输入3和4,输出7 +// ... ... +// 系统将根据您给出的测试集对学生代码进行自动评分 + +// 特别提醒:程序采用命令行传参方式,输入通过argv传入 +// 否则您的作业标准代码将不能通过测试 + +#include //引用必须头文件 +#include +using namespace std; +int main(int argc, char** argv){ + int a = atoi(argv[1]); //将第一个输入转成整型 + int b = atoi(argv[2]); //将第二个输入转换为整型 + cout< //引用必须头文件 +int main(int argc, char** argv) { + int a = atoi(argv[1]); //将第一个输入转成整型 + int b = atoi(argv[2]); //将第二个输入转换为整型 + + printf(\"%d\",a+b); //输出a+b + return 0; +}".html_safe + end + + #学生C++语言的标准代码 + def c_stantard_code_student_ + "// 同学好!这是一个C++语言的样例程序 +// 程序功能:输入两个整数,输出两者之和 +// 测试集合:老师可以给出多组测试集,例如: +// 输入1和2,输出3 +// 输入3和4,输出7 +// ... ... +// 系统将根据您给出的测试集对学生代码进行自动评分 + +// 特别提醒:程序采用命令行传参方式,输入通过argv传入 +// 否则您的作业标准代码将不能通过测试 + +#include //引用必须头文件 +#include +using namespace std; +int main(int argc, char** argv){ + int a = atoi(argv[1]); //将第一个输入转成整型 + int b = atoi(argv[2]); //将第二个输入转换为整型 + cout<&1 | base64) + if [ -z \"$compileResult\" ]; then + compileResult=$(echo -n \"compile successfully\" | base64) + fi + +} +compile $1" + end + + def execute_command + "execute(){ + #执行命令 + executeCommand=\"EXECUTECOMMAND\" + #执行文件名 + sourceClassName=${sourceClassNames[$1 - 1]} + challengeStage=$1 + + output='' + i=0 + while [[ i -lt ${#ins[*]} ]]; do + #执行,并拼接执行结果 + result=$(echo \"${ins[$i]}\" | base64 -d | $executeCommand $sourceClassName 2>&1 | base64) + #拼接输出结果 + output=$output\\\"$result\\\", + let i++ + done + output=\"[${output%?}]\" +} + +execute $1 +" + end + + def challenge_file_path + "#用户打开的文件名,之所以传过来这个,是因为可以从这个里面提取出来执行文件名 +challengeProgramNames=(CHALLENGEPROGRAMNAMES)" + end + + + def import_ke(default_opt={}) + opt = {enable_at: false, prettify: false, init_activity: false}.merge default_opt + ss = '' + + unless Setting.at_enabled? + opt[:enable_at] = false + end + + ss += javascript_include_tag("/assets/kindeditor/kindeditor",'/assets/kindeditor/pasteimg') + if opt[:enable_at] + ss += javascript_include_tag('/assets/kindeditor/at/jquery.caret.min.js', '/assets/kindeditor/at/jquery.atwho.js', '/assets/kindeditor/at/config.js') + ss += stylesheet_link_tag("/assets/kindeditor/at/jquery.atwho.css") + end + + if opt[:prettify] + ss += javascript_include_tag 'prettify' + ss += stylesheet_link_tag 'prettify' + end + + if opt[:init_activity] + ss += javascript_include_tag "create_kindeditor" + end + + ss.html_safe + end + + #竞赛动态的更新 + def update_contest_activity type, id + contest_activity = ContestActivity.where("contest_act_type=? and contest_act_id =?", type.to_s, id).first + if contest_activity + contest_activity.updated_at = Time.now + contest_activity.save + end + end + #课程动态的更新 + def update_course_activity type, id + course_activity = CourseActivity.where("course_act_type=? and course_act_id =?", type.to_s, id).first + if course_activity + course_activity.updated_at = Time.now + course_activity.save + end + end + #首页动态更新 + def update_user_activity type, id +=begin + user_activity = UserActivity.where("act_type=? and act_id =?", type.to_s, id).first + if user_activity + user_activity.updated_at = Time.now + user_activity.save + end +=end + end + #项目动态更新 + def update_forge_activity type, id + forge_activity = ForgeActivity.where("forge_act_type=? and forge_act_id=?", type.to_s, id).first + if forge_activity + forge_activity.updated_at = Time.now + forge_activity.save + end + end + #组织动态更新 + def update_org_activity type , id +=begin + org_activity = OrgActivity.where("org_act_type=? and org_act_id =?", type.to_s, id).first + if org_activity + org_activity.updated_at = Time.now + org_activity.save + end +=end + end + #个人动态更新 + def update_principal_activity type, id +=begin + principal_activity = PrincipalActivity.where("principal_act_type=? and principal_act_id =?", type.to_s, id).first + if principal_activity + principal_activity.updated_at = Time.now + principal_activity.save + end +=end + end + + #项目按更新时间排序 + def project_sort_update projects + unless projects.empty? + project_ids = '('+projects.map{|pro|pro.project_id}.join(',')+')' + sort_projects = ForgeActivity.find_by_sql("SELECT MAX(updated_at) AS updated_at,user_id, project_id FROM forge_activities WHERE project_id IN #{project_ids} GROUP BY project_id ORDER BY MAX(updated_at) DESC") + #sort_projects = sort_projects.sort_by{|sp| (!sp.project.project_score.nil? && !sp.project.project_score.commit_time.nil?) ? '' : sp.project.project_score.commit_time} + return sort_projects + end + end + + def project_sort_first projects + unless projects.empty? + project_ids = '('+projects.map{|pro|pro.project_id}.join(',')+')' + sort_projects = ForgeActivity.find_by_sql("SELECT updated_at,user_id, project_id FROM forge_activities WHERE project_id IN #{project_ids} ORDER BY updated_at DESC limit 1") + return sort_projects + end + end + + def sort_tag(content, opts) + options = {} + options[:sort_by] = opts.delete(:name) + is_current_sort = params[:sort_by].to_s == options[:sort_by] + options[:sort_direction] = is_current_sort && params[:sort_direction].to_s == 'desc' ? 'asc' : 'desc' + + path = opts.delete(:path) + "?" + params.merge(options).to_query + arrow_class = case params[:sort_direction].to_s + when 'desc' then 'fa-long-arrow-down' + when 'asc' then 'fa-long-arrow-up' + else '' + end + + content_tag(:span, opts) do + link_to path, remote: true do + content += content_tag(:i, '', class: "fa color-light-green ml5 #{arrow_class}") if is_current_sort + raw content + end + end + end +end + +def user_url_in_org(user_id) + Setting.protocol + "://" + Setting.host_name + "/users/" + user_id.to_s +end + +def project_issues_url_in_org(project_id) + Setting.protocol + "://" + Setting.host_name + "/projects/" + project_id.to_s + "/issues" +end + +def issue_url_in_org(id) + Setting.protocol + "://" + Setting.host_name + "/issues/" + id.to_s +end + +def project_boards_url_in_org(id) + Setting.protocol + "://" + Setting.host_name + "/projects/" + id.to_s + "/boards" +end + +def board_message_url_in_org(board_id, message_id) + Setting.protocol + "://" + Setting.host_name + "/boards/" + board_id.to_s + "/topics/" + message_id.to_s +end + +def project_url_in_org(id) + Setting.protocol + "://" + Setting.host_name + "/projects/" + id.to_s +end + +def homework_common_index_url_in_org(course_id) + Setting.protocol + "://" + Setting.host_name + "/homework_common?course=" + course_id.to_s +end + +def student_work_index_url_in_org(homework_id, tab = 1, is_focus = '', show_work_id = '') + if is_focus != '' + Setting.protocol + "://" + Setting.host_name + "/student_work?homework=" + homework_id.to_s + "&tab=" + tab.to_s + "&is_focus=" + is_focus.to_s + elsif show_work_id != '' + Setting.protocol + "://" + Setting.host_name + "/student_work?homework=" + homework_id.to_s + "&tab=" + tab.to_s + "&show_work_id=" + show_work_id.to_s + else + Setting.protocol + "://" + Setting.host_name + "/student_work?homework=" + homework_id.to_s + "&tab=" + tab.to_s + end +end + + +def contestant_work_index_url_in_org(work_id, tab = 1, is_focus = '', show_work_id = '') + if is_focus != '' + Setting.protocol + "://" + Setting.host_name + "/contestant_work?work=" + work_id.to_s + "&tab=" + tab.to_s + "&is_focus=" + is_focus.to_s + elsif show_work_id != '' + Setting.protocol + "://" + Setting.host_name + "/contestant_work?work=" + work_id.to_s + "&tab=" + tab.to_s + "&show_work_id=" + show_work_id.to_s + else + Setting.protocol + "://" + Setting.host_name + "/contestant_work?work=" + work_id.to_s + "&tab=" + tab.to_s + end +end + +def course_url_in_org(course_id) + Setting.protocol + "://" + Setting.host_name + "/courses/" + course_id.to_s +end + +def user_watchlist_url_in_org(id) + Setting.protocol + "://" + Setting.host_name + "/users/" + id.to_s + "/user_watchlist" +end + +def user_fanslist_url_in_org(id) + Setting.protocol + "://" + Setting.host_name + "/users/" + id.to_s + "/user_fanslist" +end + +def user_blogs_url_in_org(user_id) + Setting.protocol + "://" + Setting.host_name + "/users/" + user_id.to_s + "/blogs" +end + +def feedback_url_in_org(user_id) + Setting.protocol + "://" + Setting.host_name + "/users/" + user_id.to_s + "/user_newfeedback" +end + +def user_activities_url_in_org(user_id) + Setting.protocol + "://" + Setting.host_name + "/users/" + user_id.to_s + "/user_activities" +end + +def course_news_index_url_in_org(course_id) + Setting.protocol + "://" + Setting.host_name + "/courses/" + course_id.to_s + "/news" +end + +def news_url_in_org(news_id) + Setting.protocol + "://" + Setting.host_name + "/news/" + news_id.to_s +end + +def course_boards_url_in_org(course_id) + Setting.protocol + "://" + Setting.host_name + "/courses/" + course_id.to_s + "/boards" +end + +def logout_url_without_domain + Setting.protocol + "://" + Setting.host_name + "/logout" +end + +def signin_url_without_domain + Setting.protocol + "://" + Setting.host_name + "/login?login=true" +end + +def register_url_without_domain + Setting.protocol + "://" + Setting.host_name + "/login?login=false" +end + +def new_student_work_url_without_domain(homework_id) + Setting.protocol + "://" + Setting.host_name + "/student_work/new?homework=" + homework_id.to_s +end + +def edit_student_work_url_without_domain(homework_id) + Setting.protocol + "://" + Setting.host_name + "/student_work/" + homework_id.to_s + "/edit" +end + +def download_named_attachment_url_without_domain(id, filename, option={}) + attachment_id = (Attachment === id ? id.id : id) + Setting.protocol + "://" + Setting.host_name + "/attachments/download/" + attachment_id.to_s + "/" + filename +end + +def named_attachment_url_without_domain(id, filename, option={}) + attachment_id = (Attachment === id ? id.id : id) + Setting.protocol + "://" + Setting.host_name + "/attachments/" + attachment_id.to_s + "/" + filename +end + +#判断是否为默认的组织栏目 +def is_default_field? field + (field.name == 'activity' || field.name == 'course' || field.name == 'project' ) && field.field_type == 'default' +end + +def host_with_protocol + return Setting.protocol + "://" + Setting.host_name +end + +def secdomain_with_protocol secdomain + return Setting.protocol + "://" + secdomain + ".trustie.net" +end + +#根据回复类型获取回复 +def get_reply_by_type type, reply_id + reply = nil + case type + when 'HomeworkCommon', 'Work', 'GraduationTopic', 'GraduationTask' + reply = JournalsForMessage.find reply_id + when 'JournalsForMessage' + reply = JournalsForMessage.find reply_id + when 'Message' + reply = Message.find reply_id + when 'BlogComment' + reply = BlogComment.find reply_id + when 'OrgDocumentComment' + reply = OrgDocumentComment.find reply_id + when 'News','Comment' + reply = Comment.find reply_id + when 'Issue', 'TrainingTask' + reply = Journal.find reply_id + when 'Journal' + reply = Journal.find reply_id + when 'Syllabus' + reply = JournalsForMessage.find reply_id + when 'Memo' + reply = Memo.find reply_id + when 'Challenge' + reply = Discuss.find reply_id + end + reply +end + +#获取不包含子节点的回复(前三个) +def get_no_children_comments comments + result = {} + no_children_comments = [] + count = 0 + three_more = false + comments.each do |comment| + if comment.children.blank? + count = count + 1 + if count > 3 + three_more = true + end + break if count > 3 + no_children_comments << comment + end + end + result[:three_more] = three_more + result[:no_children_comments] = no_children_comments + result +end + +#获取不包含子节点的回复(所有) +def get_no_children_comments_all comments + no_children_comments = [] + comments.each do |comment| + if comment.children.blank? + no_children_comments << comment + end + end + no_children_comments +end + +#获取回复的所有父节点 +def get_reply_parents parents_rely, comment + unless comment.parent.nil? + parents_rely << comment.parent + get_reply_parents parents_rely, comment.parent + end + parents_rely +end + +#获取回复的所有父节点(不包括根节点) +def get_reply_parents_no_root parents_rely, comment + if !comment.parent.nil? && !comment.parent.parent.nil? + parents_rely << comment.parent + get_reply_parents_no_root parents_rely, comment.parent + end + parents_rely +end + +def get_all_children_ex result, jour + if jour.kind_of? Message + jour.children.includes(:author, :praise_tread_cache).each do |jour_child| + result << jour_child + get_all_children_ex result, jour_child + end + elsif (jour.kind_of? JournalsForMessage) || (jour.kind_of? BlogComment) || (jour.kind_of? OrgDocumentComment) + jour.children.each do |jour_child| + result << jour_child + get_all_children_ex result, jour_child + end + end + result +end + +#获取所有子节点 +def get_all_children result, jour + if jour.kind_of? Message + jour.children.includes(:author, :praise_tread_cache).each do |jour_child| + result << jour_child + get_all_children_ex result, jour_child + end + elsif (jour.kind_of? JournalsForMessage) || (jour.kind_of? BlogComment) || (jour.kind_of? OrgDocumentComment) + jour.children.each do |jour_child| + result << jour_child + get_all_children_ex result, jour_child + end + end + if jour.respond_to?(:created_on) + result.sort! { |a,b| b.created_on <=> a.created_on } + elsif jour.respond_to?(:created_at) + result.sort! { |a,b| b.created_at <=> a.created_at } + end + result +end + +#获取该节点所在的帖子 +def get_root_parent comment + while comment.parent + comment = comment.parent + end + comment +end + + + +#将有置顶属性的提到数组前面 +def sort_by_sticky topics + tmpTopics = [] + tmpIndex = 0 + topics.each do |topic| + if topic.sticky == 1 + tmpTopics[tmpIndex] = topic + tmpIndex = tmpIndex + 1 + end + end + + topics.each do |topic| + if topic.sticky == 0 + tmpTopics[tmpIndex] = topic + tmpIndex = tmpIndex + 1 + end + end + return tmpTopics +end + +#按人气排序的时候 相同的人气必须按某种时间顺序排序 有置顶属性 +def sortby_time_countcommon_hassticky topics,sortstr + tmpTopics = [] + tmpTopics = topics + tStart = -1 + tEnd = -1 + + tmpTopics_1 = [] + tmpIndex = 0 + + tmpTopics.each_with_index do |topic,index| + if topic.sticky == 0 + if tStart == -1 + if (index != tmpTopics.count-1) && (topic[:infocount] == tmpTopics[index+1][:infocount]) + tStart = index + end + else + if ((topic[:infocount] == tmpTopics[index-1][:infocount]) && ((index != tmpTopics.count-1) && (topic[:infocount] == tmpTopics[index+1][:infocount]))) + tEnd = index + else + if (topic[:infocount] == tmpTopics[index-1][:infocount]) + tEnd = index + end + if tEnd > tStart + for i in tStart..tEnd + tmpTopics_1[tmpIndex] = tmpTopics[i] + tmpIndex = tmpIndex + 1 + end + + if sortstr == "created_at" + tmpTopics_1 = tmpTopics_1.sort{|x,y| y[:created_at].to_i <=> x[:created_at].to_i } + elsif sortstr == "created_on" + tmpTopics_1 = tmpTopics_1.sort{|x,y| y[:created_on].to_i <=> x[:created_on].to_i } + elsif sortstr == "updated_at" + tmpTopics_1 = tmpTopics_1.sort{|x,y| y[:updated_at].to_i <=> x[:updated_at].to_i } + elsif sortstr == "updated_on" + tmpTopics_1 = tmpTopics_1.sort{|x,y| y[:updated_on].to_i <=> x[:updated_on].to_i } + end + + tmpIndex = 0 + for i in tStart..tEnd + tmpTopics[i] = tmpTopics_1[tmpIndex] + tmpIndex = tmpIndex + 1 + end + end + tStart = -1 + tEnd = -1 + tmpTopics_1 = [] + tmpIndex = 0 + end + end + end + end + return tmpTopics +end + +#按人气排序的时候 相同的人气必须按某种时间顺序排序 无置顶属性 +def sortby_time_countcommon_nosticky topics,sortstr + tmpTopics = [] + tmpTopics = topics + tStart = -1 + tEnd = -1 + + tmpTopics_1 = [] + tmpIndex = 0 + + tmpTopics.each_with_index do |topic,index| + if tStart == -1 + if (index != tmpTopics.count-1) && (topic[:infocount] == tmpTopics[index+1][:infocount]) + tStart = index + end + else + if ((topic[:infocount] == tmpTopics[index-1][:infocount]) && ((index != tmpTopics.count-1) && (topic[:infocount] == tmpTopics[index+1][:infocount]))) + tEnd = index + else + if (topic[:infocount] == tmpTopics[index-1][:infocount]) + tEnd = index + end + if tEnd > tStart + for i in tStart..tEnd + tmpTopics_1[tmpIndex] = tmpTopics[i] + tmpIndex = tmpIndex + 1 + end + + if sortstr == "created_at" + tmpTopics_1 = tmpTopics_1.sort{|x,y| y[:created_at].to_i <=> x[:created_at].to_i } + elsif sortstr == "created_on" + tmpTopics_1 = tmpTopics_1.sort{|x,y| y[:created_on].to_i <=> x[:created_on].to_i } + elsif sortstr == "updated_at" + tmpTopics_1 = tmpTopics_1.sort{|x,y| y[:updated_at].to_i <=> x[:updated_at].to_i } + elsif sortstr == "updated_on" + tmpTopics_1 = tmpTopics_1.sort{|x,y| y[:updated_on].to_i <=> x[:updated_on].to_i } + end + + tmpIndex = 0 + for i in tStart..tEnd + tmpTopics[i] = tmpTopics_1[tmpIndex] + tmpIndex = tmpIndex + 1 + end + end + tStart = -1 + tEnd = -1 + tmpTopics_1 = [] + tmpIndex = 0 + end + end + end + return tmpTopics +end + +def strip_html(text,len=0,endss="...") + ss = "" + if !text.nil? && text.length>0 + ss=text.gsub(/<\/?.*?>/, '').strip + ss = ss.gsub(/ */, ' ') + + if len > 0 && ss.length > len + ss = ss[0, len] + endss + elsif len > 0 && ss.length <= len + ss = ss + #ss = truncate(ss, :length => len) + end + end + return ss +end + +def message_content content + content = (strip_html content).strip + content = content.gsub(/\s+/, " ") + if content.gsub(" ", "") == "" + content = "[非文本消息]" + end + content +end + +def get_work_index(hw,is_teacher) + if is_teacher + works = hw.contest.works.order("created_at asc") + else + works = hw.contest.works.where("publish_time <= '#{Date.today}'").order("created_at asc") + end + hw_ids = works.map{|hw| hw.id} if !works.empty? + index = hw_ids.index(hw.id).to_i + return index +end + +def get_poll_index(poll, course, is_teacher) + if is_teacher + polls = course.polls.order("IF(ISNULL(publish_time),0,1),publish_time DESC, created_at DESC") + elsif User.current.member_of_course?(course) + member = course.members.where(:user_id => User.current.id).first + if member.try(:course_group_id).to_i == 0 + polls = course.polls.where("publish_time <= '#{Time.now}' and unified_setting = 1").order("IF(ISNULL(publish_time),0,1),publish_time DESC, created_at DESC") + else + not_poll_ids = course.poll_group_settings.where("course_group_id = #{member.try(:course_group_id)} and (publish_time > '#{Time.now}' or publish_time is null)") + not_poll_ids = not_poll_ids.blank? ? "(-1)" : "(" + not_poll_ids.map(&:poll_id).join(",") + ")" + polls = course.polls.where("publish_time <= '#{Time.now}' and id not in #{not_poll_ids}").order("IF(ISNULL(publish_time),0,1),publish_time DESC, created_at DESC") + end + else + polls = course.polls.where("publish_time <= '#{Time.now}'").order("IF(ISNULL(publish_time),0,1),publish_time DESC, created_at DESC") + end + poll_ids = polls.map{|poll| poll.id} if !polls.blank? + index = poll_ids.length - 1 - poll_ids.index(poll.id).to_i + return index +end + +def get_ex_index(exercise, course, is_teacher) + if is_teacher + exercises = course.exercises.order("IF(ISNULL(publish_time),0,1),publish_time DESC, created_at DESC") + elsif User.current.member_of_course?(course) + member = course.members.where(:user_id => User.current.id).first + if member.try(:course_group_id).to_i == 0 + exercises = course.exercises.where("publish_time <= '#{Time.now}' and unified_setting = 1").order("IF(ISNULL(publish_time),0,1),publish_time DESC, created_at DESC") + else + not_exercise_ids = course.exercise_group_settings.where("course_group_id = #{member.try(:course_group_id)} and (publish_time > '#{Time.now}' or publish_time is null)") + not_exercise_ids = not_exercise_ids.blank? ? "(-1)" : "(" + not_exercise_ids.map(&:exercise_id).join(",") + ")" + exercises = course.exercises.where("publish_time <= '#{Time.now}' and id not in #{not_exercise_ids}").order("IF(ISNULL(publish_time),0,1),publish_time DESC, created_at DESC") + end + else + exercises = course.exercises.where("publish_time <= '#{Time.now}'").order("IF(ISNULL(publish_time),0,1),publish_time DESC, created_at DESC") + end + ex_ids = exercises.map{|ex| ex.id} if !exercises.blank? + index = ex_ids.length - 1 - ex_ids.index(exercise.id).to_i + return index +end + +def get_task_index task, is_teacher + if is_teacher + tasks = task.course.graduation_tasks.order("IF(ISNULL(publish_time),0,1),publish_time DESC, created_at DESC") + else + tasks = task.course.graduation_tasks.where("publish_time <= '#{Time.now}'").order("IF(ISNULL(publish_time),0,1),publish_time DESC, created_at DESC") + end + task_ids = tasks.pluck(:id) + index = task_ids.length - task_ids.index(task.id).to_i + return index +end + +def get_hw_index(hw,is_teacher,type=0) + homework_commons = hw.course.homework_commons + course = hw.course + category_str = hw.course_homework_category_id.nil? ? "is null" : "= #{hw.course_homework_category_id}" + if is_teacher + if type != 0 + homeworks = homework_commons.where("homework_commons.homework_type = #{type} and course_homework_category_id #{category_str}").order("IF(ISNULL(publish_time),0,1),publish_time DESC, created_at DESC") + else + homeworks = homework_commons.where("course_homework_category_id #{category_str}").order("publish_time desc") + end + elsif User.current.member_of_course?(course) + member = course.members.where(:user_id => User.current.id).first + if member.try(:course_group_id).to_i == 0 + if type != 0 + homeworks = homework_commons.where("course_homework_category_id #{category_str} and homework_commons.homework_type = #{type} and publish_time <= '#{Time.now}' and unified_setting = 1").order("IF(ISNULL(publish_time),0,1),publish_time DESC, created_at DESC") + else + homeworks = homework_commons.where("course_homework_category_id #{category_str} and publish_time <= '#{Time.now}' and unified_setting = 1").order("IF(ISNULL(publish_time),0,1),publish_time DESC, created_at DESC") + end + else + not_homework_ids = course.homework_group_settings.where("course_group_id = #{member.try(:course_group_id)} and (publish_time > '#{Time.now}' or publish_time is null)") + not_homework_ids = not_homework_ids.blank? ? "(-1)" : "(" + not_homework_ids.map(&:homework_common_id).join(",") + ")" + if type != 0 + homeworks = homework_commons.where("course_homework_category_id #{category_str} and homework_commons.homework_type = #{type} and publish_time <= '#{Time.now}' and id not in #{not_homework_ids}").order("IF(ISNULL(publish_time),0,1),publish_time DESC, created_at DESC") + else + homeworks = homework_commons.where("course_homework_category_id #{category_str} and publish_time <= '#{Time.now}' and id not in #{not_homework_ids}").order("IF(ISNULL(publish_time),0,1),publish_time DESC, created_at DESC") + end + end + else + if type != 0 + homeworks = homework_commons.where("course_homework_category_id #{category_str} and homework_commons.homework_type = #{type} and publish_time <= '#{Time.now}'").order("IF(ISNULL(publish_time),0,1),publish_time DESC, created_at DESC") + else + homeworks = homework_commons.where("course_homework_category_id #{category_str} and publish_time <= '#{Time.now}'").order("IF(ISNULL(publish_time),0,1),publish_time DESC, created_at DESC") + end + end + hw_ids = homeworks.map{|hw| hw.id} if !homeworks.blank? + index = hw_ids.blank? ? 1 : (hw_ids.length - 1 - hw_ids.index(hw.id).to_i) + return index +end + +def get_hw_status homework_common + str = "" + if homework_common.homework_detail_manual + if homework_common.homework_detail_manual.comment_status == 0 && homework_common.publish_time.nil? + str += '未发布' + elsif homework_common.homework_detail_manual.comment_status == 0 + str += '未发布' + elsif homework_common.homework_detail_manual.comment_status == 1 + if homework_common.anonymous_comment == 0 + str += '未开启匿评' + else + str += '匿评已禁用' + end + if homework_common.end_time >= Time.now + str += '作品提交中' + elsif homework_common.end_time < Time.now && homework_common.anonymous_comment == 1 && User.current.allowed_to?(:as_teacher, homework_common.course) + str += '教师评阅中' + else + str += '作品补交中' + end + elsif homework_common.homework_detail_manual.comment_status == 2 + if homework_common.anonymous_comment == 0 + str += '匿评中' + else + str += '匿评已禁用' + end + str += '教师评阅中' + elsif homework_common.homework_detail_manual.comment_status == 3 + if homework_common.anonymous_comment == 0 + str += '匿评已结束' + else + str += '匿评已禁用' + end + str += '教师评阅中' + end + end + str +end + +def get_cw_status contest_work + str = "" + if contest_work.work_status == 0 && contest_work.publish_time.nil? + str += '挂起' + elsif contest_work.work_status == 0 + str += '未发布' + elsif contest_work.work_status == 1 + if Time.parse(contest_work.end_time.to_s).strftime("%Y-%m-%d") >= Time.now.strftime("%Y-%m-%d") + str += '作品提交中' + else + str += '作品补交中' + end + elsif contest_work.work_status == 2 + str += '提交已截止' + elsif contest_work.work_status == 3 + str += '在线评审中' + elsif contest_work.work_status == 4 + str += '评审已截止' + end + str +end + + +def get_group_member_names user_ids + result = "" + user_ids.each do |user_id| + user = User.where(:id => user_id).first + unless user.nil? + if result != "" + result += "、#{user.show_name}" + else + result += user.show_name + end + end + end + result +end + +def get_contest_group_member_names work + result = "" + unless work.nil? + work.contestant_work_projects.each do |member| + user = User.where(:id => member.user_id).first + unless user.nil? + if result != "" + result += "、#{user.show_name}" + else + result += user.show_name + end + end + end + end + result +end + +def course_syllabus_option syllabus_id = nil + syllabus_members = SyllabusMember.where("user_id = #{User.current.id}") + syllabus_ids = syllabus_members.map{|mem| mem.syllabus_id} + if syllabus_id && !syllabus_ids.include?(syllabus_id) + syllabus_ids << syllabus_id + end + syllabus_ids = syllabus_ids.empty? ? "(-1)" : "(" + syllabus_ids.join(',') + ")" + syllabuses = Syllabus.where("id in #{syllabus_ids}") + type = [] + option1 = [] + option1 << "请选择课程" + option1 << 0 + type << option1 + unless syllabuses.empty? + syllabuses.each do |syllabus| + option = [] + option << syllabus.title + option << syllabus.id + type << option + end + end + type +end + +def create_polls_tiding poll, members + tid_str = "" + if poll.tidings.where(:parent_container_type => "PollPublish", :user_id => poll.course.teachers.map(&:user_id)).count == 0 + poll.course.teachers.find_each do |member| + tid_str += "," if tid_str != "" + tid_str += "(#{member.user_id}, #{poll.user_id}, #{poll.id}, 'Poll', #{poll.id}, 'PollPublish', #{poll.course.id}, 'Course', 0, 'Poll', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}')" + end + end + + members.find_each do |student| + tid_str += "," if tid_str != "" + tid_str += "(#{student.user_id}, #{poll.user_id}, #{poll.id}, 'Poll', #{poll.id}, 'PollPublish', #{poll.course_id}, 'Course', 0, 'Poll', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}')" + end + + if tid_str != "" + tid_sql = "insert into tidings (user_id, trigger_user_id, container_id, container_type, parent_container_id, parent_container_type, belong_container_id, belong_container_type, viewed, tiding_type, created_at, updated_at) values" + tid_str + ActiveRecord::Base.connection.execute tid_sql + end +end + +def create_polls_list poll + str = "" + poll.course.student.find_each do |student| + str += "," if str != "" + str += "(#{student.user_id},#{poll.id}, 0, '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}')" + end + + if str != "" + sql = "insert into poll_users (user_id, poll_id, commit_status, created_at, updated_at) values" + str + ActiveRecord::Base.connection.execute sql + end +end + +def create_exercises_tiding exercise, members + tid_str = "" + if exercise.tidings.where(:parent_container_type => "ExercisePublish", :user_id => exercise.course.teachers.map(&:user_id)).count == 0 + exercise.course.teachers.find_each do |member| + tid_str += "," if tid_str != "" + tid_str += "(#{member.user_id}, #{exercise.user_id}, #{exercise.id}, 'Exercise', #{exercise.id}, 'ExercisePublish', #{exercise.course.id}, 'Course', 0, 'Exercise', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}')" + end + end + + members.find_each do |student| + tid_str += "," if tid_str != "" + tid_str += "(#{student.user_id}, #{exercise.user_id}, #{exercise.id}, 'Exercise', #{exercise.id}, 'ExercisePublish', #{exercise.course_id}, 'Course', 0, 'Exercise', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}')" + end + + if tid_str != "" + tid_sql = "insert into tidings (user_id, trigger_user_id, container_id, container_type, parent_container_id, parent_container_type, belong_container_id, belong_container_type, viewed, tiding_type, created_at, updated_at) values" + tid_str + ActiveRecord::Base.connection.execute tid_sql + end +end + +def create_exercises_list exercise + str = "" + exercise.course.student.find_each do |student| + str += "," if str != "" + str += "(#{student.user_id}, #{exercise.id}, 0, '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}')" + end + + if str != "" + sql = "insert into exercise_users (user_id, exercise_id, commit_status, created_at, updated_at) values" + str + ActiveRecord::Base.connection.execute sql + end +end + +def create_works_tiding homework, members + tid_str = "" + if homework.tidings.where(:parent_container_type => "HomeworkPublish", :user_id => homework.course.teachers.map(&:user_id)).count == 0 + homework.course.teachers.find_each do |member| + tid_str += "," if tid_str != "" + tid_str += "(#{member.user_id}, #{homework.user_id}, #{homework.id}, 'HomeworkCommon', #{homework.id}, 'HomeworkPublish', #{homework.course.id}, 'Course', 0, 'HomeworkCommon', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}')" + end + end + members.find_each do |student| + tid_str += "," if tid_str != "" + tid_str += "(#{student.user_id}, #{homework.user_id}, #{homework.id}, 'HomeworkCommon', #{homework.id}, 'HomeworkPublish', #{homework.course_id}, 'Course', 0, 'HomeworkCommon', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}')" + end + if tid_str != "" + tid_sql = "insert into tidings (user_id, trigger_user_id, container_id, container_type, parent_container_id, parent_container_type, belong_container_id, belong_container_type, viewed, tiding_type, created_at, updated_at) values" + tid_str + ActiveRecord::Base.connection.execute tid_sql + end +end + +def create_works_list homework + if homework.course.present? && homework.course.student.count > 0 + str = "" + name = homework.name + name_str = name + "的作品提交" + homework.course.student.each do |student| + str += "," if str != "" + str += "('#{name_str}',#{homework.id},#{student.user_id}, '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}')" + end + if str != "" + sql = "insert into student_works (name, homework_common_id, user_id, created_at, updated_at) values" + str + ActiveRecord::Base.connection.execute sql + end + end +end + +def add_to_homework_bank_f homework + homework_bank = HomeworkBank.new(:name => homework.name, :description => homework.description, :user_id => User.current.id, :homework_type => homework.homework_type, + :quotes => 1, :is_public => 0, :applicable_syllabus => homework.course.course_list_name, :homework_common_id => homework.id, + :reference_answer => homework.reference_answer, :course_list_id => homework.course.course_list_id) + if homework.homework_type == 2 && homework.homework_detail_programing + homework_bank.language = homework.homework_detail_programing.language + homework.homework_tests.each_with_index do |homework_test| + homework_bank.homework_bank_tests << HomeworkBankTest.new( + input: homework_test.input, + output: homework_test.output + ) + end + homework.homework_samples.each_with_index do |homework_test| + homework_bank.homework_bank_samples << HomeworkBankSample.new( + input: homework_test.input, + output: homework_test.output + ) + end + elsif homework.homework_type == 3 && homework.homework_detail_group + homework_bank.min_num = homework.homework_detail_group.min_num + homework_bank.max_num = homework.homework_detail_group.max_num + homework_bank.base_on_project = homework.homework_detail_group.base_on_project + end + homework.attachments.each do |attachment| + att = attachment.copy + att.container_id = nil + att.container_type = nil + att.author_id = homework_bank.user_id + att.copy_from = attachment.id + att.save + homework_bank.attachments << att + end + homework_bank +end + +# 获取项目动态更新时间 +def get_forge_act_message(act, type) + forge_act = ForgeActivity.where(:forge_act_id => act.id, :forge_act_type => type).first + format_time(forge_act.nil? ? act.created_on : forge_act.try(:updated_at)) +end + +#作业类型 +def homework_type_option + type = [] + option0 = [] + option0 << "请选择作业类型" + option0 << 0 + option1 = [] + option1 << "普通作业" + option1 << 1 + option2 = [] + option2 << "编程作业" + option2 << 2 + option3 = [] + option3 << "分组作业" + option3 << 3 + type << option0 + type << option1 + type << option2 + type << option3 + type +end + +# 竞赛题目类型 +def work_type_option + type = [] + option0 = [] + option0 << "请选择竞赛类型" + option0 << 0 + option1 = [] + option1 << "普通竞赛" + option1 << 1 + # option2 = [] + # option2 << "编程作业" + # option2 << 2 + option3 = [] + option3 << "团队竞赛" + option3 << 3 + type << option0 + type << option1 + #type << option2 + type << option3 + type +end + +# 当前用户可见的某竞赛下的作品数 +def visable_contest_work contest + if User.current.admin? || User.current.admin_of_contest?(contest) + work_num = contest.works.count + else + work_num = contest.works.where("work_status > 0").count + end + work_num +end + +def searchstudent_by_name users, name + mems = [] + if name != "" + name = name.to_s.downcase + users.each do |m| + username = m.lastname.to_s.downcase + m.firstname.to_s.downcase + if(m.login.to_s.downcase.include?(name) || m.user_extensions[:student_id].to_s.downcase.include?(name) || username.include?(name)) + mems << m + end + end + else + mems = users + end + mems +end + +def contest_feedback_count + @contest.journals_for_messages.where('m_parent_id IS NULL').count +end + +def add_reply_adapter obj, options + #modify by nwb + #添加对课程留言的支持 + #留言回复应该不关系其所属的Class,而关心的是其所属的父留言 + case obj.jour_type + when 'Principal' + obj.jour.add_jour(nil, nil, nil, options) + when 'Project' + Project.add_new_jour(nil, nil, obj.jour_id, options) + when 'Course' + Course.add_new_jour(nil, nil, obj.jour_id, options) + when 'Contest' + Contest.add_new_jour(nil, nil, obj.jour_id, options) + #when 'Bid' + # obj.jour.add_jour(nil, nil, nil, options) + #when 'Contest' + # obj.jour.add_jour(nil, nil, obj.jour_id, options) + #when 'Softapplication' + # obj.jour.add_jour(nil, nil, obj.jour_id, options) + #when 'HomeworkAttach' + # obj.jour.add_jour(nil, nil, obj.jour_id, options) + end + # obj = obj_distinguish_url_origin || User.find_by_id(2) + # if obj.kind_of? User + # obj.add_jour(nil, nil, nil, options) + # elsif obj.kind_of? Project + # Project.add_new_jour(nil, nil, obj.id, options) + # elsif obj.kind_of? Course + # Course.add_new_jour(nil, nil, obj.id, options) + # elsif obj.kind_of? Bid + # obj.add_jour(nil, nil, nil, options) + # elsif obj.kind_of? Contest + # obj.add_jour(nil, nil, obj.id, options) #new added + # elsif obj.kind_of? Softapplication + # obj.add_jour(nil, nil, obj.id, options) #new added + # elsif obj.kind_of? HomeworkAttach + # obj.add_jour(nil, nil, obj.id, options) #new added + # else + # raise "create reply obj unknow type.#{obj.class}" + # end +end + +def sy_resources syllabus + courses = syllabus.courses.not_deleted + attachments = Attachment.where(:container_type => 'Course', :container_id => courses.map(&:id)) + resources = ResourceBank.where(:id => attachments.map(&:resource_bank_id)) + resources +end + +def sy_homeworks syllabus + courses = syllabus.courses.not_deleted + homeworks = HomeworkCommon.where(:course_id => courses.map(&:id)) + homeworks = HomeworkBank.where(:id => homeworks.map(&:homework_bank_id)) + homeworks +end + +# 课堂学生的评测次数 +def course_eval_count course + Output.find_by_sql("select sum(g.evaluate_count) as evaluating_count from games g inner join + (select myshixun_id from student_works sw inner join homework_commons hc on sw.homework_common_id=hc.id and + sw.myshixun_id !=0 and hc.course_id=#{course.id} and homework_type=4) aa on g.myshixun_id=aa.myshixun_id").first.try(:evaluating_count).to_i +end + +# 可以查看到资源库的资源 +def visable_attachemnts_incourse course + return[] unless course + result = [] + course.attachments.each do |attachment| + if attachment.unified_setting + if attachment.is_public? && attachment.is_publish == 1 || User.current == attachment.author || User.current.allowed_to?(:as_teacher,course) || (User.current.member_of_course?(course) && attachment.is_publish == 1) || User.current.admin? + result << attachment + end + else + if attachment.is_public? && attachment.is_publish == 1 && !User.current.member_of_course?(course) || User.current == attachment.author || User.current.allowed_to?(:as_teacher,course) || User.current.admin? + result << attachment + elsif User.current.member_of_course?(course) && attachment.is_publish == 1 + member = course.members.where(:user_id => User.current.id).first + if member.try(:course_group_id).to_i == 0 && attachment.unified_setting + result << attachment + elsif attachment.attachment_group_settings.where("course_group_id = #{member.try(:course_group_id)} and publish_time > '#{Time.now}'").count == 0 + result << attachment + end + end + end + end + result +end + +def visable_course_poll course, is_teacher + if is_teacher + poll_num = course.polls.count + elsif User.current.member_of_course?(course) + member = course.members.where(:user_id => User.current.id).first + if member.try(:course_group_id).to_i == 0 + poll_num = course.polls.where("publish_time <= '#{Time.now}' and unified_setting = 1").count + else + not_poll_ids = course.poll_group_settings.where("course_group_id = #{member.try(:course_group_id)} and (publish_time > '#{Time.now}' or publish_time is null)") + not_poll_ids = not_poll_ids.blank? ? "(-1)" : "(" + not_poll_ids.map(&:poll_id).join(",") + ")" + poll_num = course.polls.where("publish_time <= '#{Time.now}' and id not in #{not_poll_ids}").count + end + else + poll_num = course.polls.where("publish_time <= '#{Time.now}' and unified_setting = 1").count + end + poll_num +end + +def visable_course_exercise course, is_teacher + if is_teacher + exercise_num = course.exercises.count + elsif User.current.member_of_course?(course) + member = course.members.where(:user_id => User.current.id).first + if member.try(:course_group_id).to_i == 0 + exercise_num = course.exercises.where("publish_time <= '#{Time.now}' and unified_setting = 1").count + else + not_exercise_ids = course.exercise_group_settings.where("course_group_id = #{member.try(:course_group_id)} and (publish_time > '#{Time.now}' or publish_time is null)") + not_exercise_ids = not_exercise_ids.blank? ? "(-1)" : "(" + not_exercise_ids.map(&:exercise_id).join(",") + ")" + exercise_num = course.exercises.where("publish_time <= '#{Time.now}' and id not in #{not_exercise_ids}").count + end + else + exercise_num = course.exercises.where("publish_time <= '#{Time.now}' and unified_setting = 1").count + end + exercise_num +end + +def visable_course_homework course, type=0, is_teacher, category_id + category_str = category_id.nil? ? "is null" : "= #{category_id}" + if is_teacher + if type != 0 + homework_num = course.homework_commons.where("homework_type = #{type} and course_homework_category_id #{category_str}").count + else + homework_num = course.homework_commons.where(:homework_type => [1,3,4]).count + end + elsif User.current.member_of_course?(course) + member = course.members.where(:user_id => User.current.id).first + if member.try(:course_group_id).to_i == 0 + if type != 0 + homework_num = course.homework_commons.where("homework_commons.homework_type = #{type} and publish_time <= '#{Time.now}' and unified_setting = 1 and course_homework_category_id #{category_str}").count + else + homework_num = course.homework_commons.where("homework_type in (1, 3, 4) and publish_time <= '#{Time.now}' and unified_setting = 1").count + end + else + not_homework_ids = course.homework_group_settings.where("course_group_id = #{member.try(:course_group_id)} and (publish_time > '#{Time.now}' or publish_time is null)") + not_homework_ids = not_homework_ids.blank? ? "(-1)" : "(" + not_homework_ids.map(&:homework_common_id).join(",") + ")" + if type != 0 + homework_num = course.homework_commons.where("homework_commons.homework_type = #{type} and publish_time <= '#{Time.now}' and id not in #{not_homework_ids} and course_homework_category_id #{category_str}").count + else + homework_num = course.homework_commons.where("homework_type in (1, 3, 4) and publish_time <= '#{Time.now}' and id not in #{not_homework_ids}").count + end + end + else + if type != 0 + homework_num = course.homework_commons.where("homework_type = #{type} and publish_time <= '#{Time.now}' and unified_setting = 1 and course_homework_category_id #{category_str}").count + else + homework_num = course.homework_commons.where("homework_type in (1, 3, 4) and publish_time <= '#{Time.now}' and unified_setting = 1").count + end + end + homework_num +end + +def visible_task_count course, is_teacher + task_count = 0 + if is_teacher + task_count = course.graduation_tasks.count + else + task_count = course.graduation_tasks.where("publish_time <= '#{Time.now}'").count + end + task_count +end + +def update_shixun_work_status homework + shixun = homework.shixuns.first + student_works = homework.student_works.where(:work_status => 0) + homework_challenge_settings = homework.homework_challenge_settings + challeng_ids = homework_challenge_settings.map(&:challenge_id) + # 取已发布的作品 + if homework.unified_setting + student_works = student_works + else + setting = homework.homework_group_settings.where("publish_time < '#{Time.now}'") + if setting.blank? + student_works = student_works.where("0=1") + else + users = homework.course.members.where(:course_group_id => setting.map(&:course_group_id)) + student_works = student_works.where(:user_id => users.map(&:user_id)) + end + end + # 已发布作品且状态为未提交的作品 如果有开启过实训则更新状态 + myshixuns = Myshixun.where(:shixun_id => shixun.id, :user_id => student_works.map(&:user_id)) + myshixuns.each do |myshixun| + work = student_works.where(:user_id => myshixun.user_id).first + member = Member.find_by_sql("select course_group_id from members where course_id = #{homework.course_id} and user_id = #{work.user_id}").first + setting_time = homework_group_setting homework, member.try(:course_group_id) + games = myshixun.games.where(:challenge_id => challeng_ids) + myshixun_endtime = games.select{|game| game.status == 2}.size == games.size ? games.map(&:end_time).max : nil + compelete_status = 0 + if myshixun_endtime.present? && myshixun_endtime < setting_time.end_time + if myshixun_endtime < setting_time.publish_time + compelete_status = 2 + else + compelete_status = 1 + end + end + if setting_time.end_time > Time.now + work.update_attributes(:work_status => 1, :late_penalty => 0, :commit_time => myshixun.updated_at, :update_time => myshixun.updated_at, :myshixun_id => myshixun.id, :compelete_status => compelete_status) + else + work.update_attributes(:work_status => ((myshixun.is_complete? && (myshixun.done_time < setting_time.end_time)) ? 1 : 2), :late_penalty => (myshixun.is_complete? && (myshixun.done_time < setting_time.end_time) ? 0 : homework.late_penalty), :commit_time => myshixun.updated_at, :update_time => myshixun.updated_at, :myshixun_id => myshixun.id, :compelete_status => compelete_status) + end + set_shixun_final_score work, homework.homework_detail_manual.answer_open_evaluation, homework_challenge_settings + end + # 更新所有学生的效率分 + update_student_eff_score HomeworkCommon.where(:id => homework.id).first +=begin + student_works.each do |work| + if work.work_status == 0 + myshixun = Myshixun.where(:shixun_id => shixun.id, :user_id => work.user_id).first + if myshixun + member = Member.find_by_sql("select course_group_id from members where course_id = #{homework.course_id} and user_id = #{User.current.id}").first + setting_time = homework_group_setting homework, member.try(:course_group_id) + if setting_time.end_time > Time.now + work.update_attributes(:work_status => 1, :late_penalty => 0, :commit_time => myshixun.updated_at, :update_time => myshixun.updated_at, :myshixun_id => myshixun.id) + else + work.update_attributes(:work_status => ((myshixun.is_complete? && (myshixun.done_time < setting_time.end_time)) ? 1 : 2), :late_penalty => (myshixun.is_complete? && (myshixun.done_time < setting_time.end_time) ? 0 : homework.late_penalty), :commit_time => myshixun.updated_at, :update_time => myshixun.updated_at, :myshixun_id => myshixun.id) + end + end + end + set_shixun_final_score work, homework.homework_detail_manual.answer_open_evaluation, homework_challenge_settings + end +=end +end + +#成绩计算 +def set_final_score homework,student_work + if homework && homework.homework_detail_manual && !student_work.ultimate_score + if !homework.homework_detail_manual.final_mode + tea_ass_proportion = homework.homework_detail_manual.ta_proportion + tea_proportion = homework.homework_detail_manual.te_proportion + if homework.homework_type != 2 #非编程作业 + if student_work.teacher_score + if student_work.teaching_asistant_score.nil? + if student_work.student_score.nil? + student_work.final_score = student_work.teacher_score + else + te_proportion = tea_proportion + tea_ass_proportion / 2 + final_te_score = BigDecimal.new("#{student_work.teacher_score}") * BigDecimal.new("#{te_proportion}") + final_s_score = BigDecimal.new("#{student_work.student_score}") * (BigDecimal.new('1.0') - BigDecimal.new("#{te_proportion}")) + final_score = final_te_score + final_s_score + student_work.final_score = format("%.2f",final_score.to_f) + end + else + if student_work.student_score.nil? + te_proportion = tea_proportion + (1.0 - tea_proportion - tea_ass_proportion) / 2 + final_te_score = BigDecimal.new("#{student_work.teacher_score}") * BigDecimal.new("#{te_proportion}") + final_ta_score = BigDecimal.new("#{student_work.teaching_asistant_score}") * (BigDecimal.new('1.0') - BigDecimal.new("#{te_proportion}")) + final_score = final_te_score + final_ta_score + student_work.final_score = format("%.2f",final_score.to_f) + else + final_te_score = BigDecimal.new("#{student_work.teacher_score}") * BigDecimal.new("#{tea_proportion}") + final_ta_score = BigDecimal.new("#{student_work.teaching_asistant_score}") * BigDecimal.new("#{tea_ass_proportion}") + final_s_score = BigDecimal.new("#{student_work.student_score}") * (BigDecimal.new('1.0') - BigDecimal.new("#{tea_proportion}") - BigDecimal.new("#{tea_ass_proportion}")) + final_score = final_te_score + final_ta_score + final_s_score + student_work.final_score = format("%.2f",final_score.to_f) + end + end + else + if student_work.teaching_asistant_score.nil? + student_work.final_score = student_work.student_score + elsif student_work.student_score.nil? + student_work.final_score = student_work.teaching_asistant_score + else + ta_proportion = tea_ass_proportion + tea_proportion / 2 + final_ta_score = BigDecimal.new("#{student_work.teaching_asistant_score}") * BigDecimal.new("#{ta_proportion}") + final_s_score = BigDecimal.new("#{student_work.student_score}") * (BigDecimal.new('1.0') - BigDecimal.new("#{ta_proportion}")) + final_score = final_ta_score + final_s_score + student_work.final_score = format("%.2f",final_score.to_f) + end + end + elsif homework.homework_type == 2 && homework.homework_detail_programing #编程作业-----设定:系统评分必定不为空 + #if homework.teacher_priority == 1 #教师优先 + sy_proportion = homework.homework_detail_programing.ta_proportion + if student_work.teacher_score + if student_work.teaching_asistant_score.nil? #教辅未评分 + if student_work.student_score.nil? + ta_proportion = tea_proportion + (1 - tea_proportion - sy_proportion) / 2 + final_te_score = BigDecimal.new("#{student_work.teacher_score}") * BigDecimal.new("#{ta_proportion}") + final_sy_score = BigDecimal.new("#{student_work.system_score || 0}") * (BigDecimal.new('1.0') - BigDecimal.new("#{ta_proportion}")) + final_score = final_sy_score + final_te_score + student_work.final_score = format("%.2f",final_score.to_f) + else + rest_proportion = tea_ass_proportion / 3 + final_sy_score = BigDecimal.new("#{student_work.system_score || 0}") * BigDecimal.new("#{sy_proportion + rest_proportion}") + final_te_score = BigDecimal.new("#{student_work.teacher_score}") * BigDecimal.new("#{tea_proportion + rest_proportion}") + final_st_score = BigDecimal.new("#{student_work.student_score}") * (BigDecimal.new('1.0') - BigDecimal.new("#{sy_proportion + rest_proportion}") - BigDecimal.new("#{tea_proportion + rest_proportion}")) + final_score = final_sy_score + final_te_score + final_st_score + student_work.final_score = format("%.2f",final_score.to_f) + end + elsif student_work.student_score.nil? #学生未评分 + rest_proportion = (1 - tea_proportion - sy_proportion - tea_ass_proportion) / 3 + final_sy_score = BigDecimal.new("#{student_work.system_score || 0}") * BigDecimal.new("#{sy_proportion + rest_proportion}") + final_te_score = BigDecimal.new("#{student_work.teacher_score}") * BigDecimal.new("#{tea_proportion + rest_proportion}") + final_ta_score = BigDecimal.new("#{student_work.teaching_asistant_score}") * (BigDecimal.new('1.0') - BigDecimal.new("#{sy_proportion + rest_proportion}") - BigDecimal.new("#{tea_proportion + rest_proportion}")) + final_score = final_sy_score + final_te_score + final_ta_score + student_work.final_score = format("%.2f",final_score.to_f) + else + final_sy_score = BigDecimal.new("#{student_work.system_score || 0}") * BigDecimal.new("#{sy_proportion}") + final_te_score = BigDecimal.new("#{student_work.teacher_score}") * BigDecimal.new("#{tea_proportion}") + final_ta_score = BigDecimal.new("#{student_work.teaching_asistant_score}") * BigDecimal.new("#{tea_ass_proportion}") + final_s_score = BigDecimal.new("#{student_work.student_score}") * (BigDecimal.new('1.0') - BigDecimal.new("#{sy_proportion}") - BigDecimal.new("#{tea_proportion}") - BigDecimal.new("#{tea_ass_proportion}")) + final_score = final_sy_score + final_ta_score + final_te_score + final_st_score + student_work.final_score = format("%.2f",final_score.to_f) + end + else + if student_work.teaching_asistant_score.nil? #教辅未评分 + if student_work.student_score.nil? + student_work.final_score = student_work.system_score + else + ta_proportion = sy_proportion + (tea_ass_proportion + tea_proportion) / 2 + final_sy_score = BigDecimal.new("#{student_work.system_score || 0}") * BigDecimal.new("#{ta_proportion}") + final_st_score = BigDecimal.new("#{student_work.student_score}") * (BigDecimal.new('1.0') - BigDecimal.new("#{ta_proportion}")) + final_score = final_sy_score + final_st_score + student_work.final_score = format("%.2f",final_score.to_f) + end + elsif student_work.student_score.nil? #学生未评分 + if student_work.teaching_asistant_score.nil? + student_work.final_score = student_work.system_score + else + ta_proportion = sy_proportion + (1.0 - tea_ass_proportion - sy_proportion) / 2 + final_sy_score = BigDecimal.new("#{student_work.system_score || 0}") * BigDecimal.new("#{ta_proportion}") + final_ts_score = BigDecimal.new("#{student_work.teaching_asistant_score}") * (BigDecimal.new('1.0') - BigDecimal.new("#{ta_proportion}")) + final_score = final_sy_score + final_ts_score + student_work.final_score = format("%.2f",final_score.to_f) + end + else + rest_proportion = tea_proportion / 3 + final_sy_score = BigDecimal.new("#{student_work.system_score || 0}") * BigDecimal.new("#{sy_proportion + rest_proportion}") + final_ts_score = BigDecimal.new("#{student_work.teaching_asistant_score}") * BigDecimal.new("#{tea_ass_proportion + rest_proportion}") + final_st_score = BigDecimal.new("#{student_work.student_score}") * (BigDecimal.new('1.0') - BigDecimal.new("#{sy_proportion + rest_proportion}") - BigDecimal.new("#{tea_ass_proportion + rest_proportion}")) + final_score = final_sy_score + final_ts_score + final_st_score + student_work.final_score = format("%.2f",final_score.to_f) + end + end + end + else + if homework.homework_type != 2 + if student_work.teacher_score + student_work.final_score = student_work.teacher_score + else + if student_work.teaching_asistant_score.nil? + student_work.final_score = student_work.student_score + else + student_work.final_score = student_work.teaching_asistant_score + end + end + elsif homework.homework_type == 2 && homework.homework_detail_programing + if student_work.teacher_score + student_work.final_score = student_work.teacher_score + else + if student_work.teaching_asistant_score + student_work.final_score = student_work.teaching_asistant_score + else + if student_work.system_score + student_work.final_score = student_work.system_score + else + student_work.final_score = student_work.student_score + end + end + end + end + end + if student_work.final_score + score = student_work.final_score - student_work.absence_penalty - student_work.late_penalty - student_work.appeal_penalty + student_work.work_score = format("%.2f",(score < 0 ? 0 : score).to_f) if score + else + student_work.work_score = nil + end + end +end + +# 计算实训作品学生的效率分 +def update_student_eff_score homework + if homework.work_efficiency && homework.max_efficiency != 0 + homework.student_works.where("compelete_status != 0").each do |student_work| + eff_score = student_work.efficiency / homework.max_efficiency * homework.eff_score + student_work.eff_score = format("%.2f", eff_score) + unless student_work.ultimate_score + work_score = student_work.final_score + student_work.eff_score - student_work.late_penalty + student_work.work_score = format("%.2f", work_score < 0 ? 0 : work_score) + end + student_work.save + end + else + homework.student_works.where("compelete_status != 0").each do |student_work| + student_work.eff_score = 0 + unless student_work.ultimate_score + work_score = student_work.final_score + student_work.eff_score - student_work.late_penalty + student_work.work_score = format("%.2f", work_score < 0 ? 0 : work_score) + end + student_work.save + end + end +end + +# 实训作业的评分 +def set_shixun_final_score student_work, answer_open_evaluation, homework_challenge_settings + unless student_work.work_status == 0 + myshixun = student_work.myshixun + final_score = 0 + compelete = true + max_endtime = "" + user_total_score = 0 + pass_consume_time = 0 + homework_challenge_settings.each do |setting| + game = myshixun.games.where(:challenge_id => setting.challenge_id, :status => 2).first + unless game.nil? + pass_consume_time += (game.cost_time / 60.0).to_f + user_total_score += game.final_score.to_i < 0 ? 0 : game.challenge.score.to_i + adjust_score = student_work.challenge_work_scores.where(:challenge_id => setting.challenge_id).last + final_score += adjust_score.present? ? adjust_score.score : (answer_open_evaluation ? setting.score : (game.final_score >= 0 ? setting.score : 0)) + max_endtime = max_endtime == "" ? game.end_time : (game.end_time > max_endtime ? game.end_time : max_endtime) + else + compelete = false + end + end + + efficiency = (pass_consume_time == 0 ? 0 : Math.log((user_total_score / pass_consume_time.to_f) + 1.0)) + student_work.efficiency = efficiency < 0 ? 0 : format("%.2f", efficiency) + + if compelete && max_endtime != "" + homework = student_work.homework_common + member = Member.find_by_sql("select course_group_id from members where course_id = #{homework.course_id} and user_id = #{student_work.user_id}").first + setting_time = homework_group_setting homework, member.try(:course_group_id) + if setting_time.publish_time.present? && setting_time.end_time.present? + if max_endtime < setting_time.publish_time + student_work.compelete_status = 2 + else + if max_endtime < setting_time.end_time || (homework.allow_late && (homework.course.end_date.nil? || max_endtime < homework.course.end_date.end_of_day)) + student_work.compelete_status = 1 + student_work.cost_time = max_endtime.to_i - setting_time.publish_time.to_i + else + student_work.compelete_status = 0 + end + end + end + + if homework.work_efficiency + if homework.max_efficiency < student_work.efficiency + homework.max_efficiency = student_work.efficiency + homework.update_column("max_efficiency", homework.max_efficiency) + end + eff_score = homework.max_efficiency == 0 ? 0 : student_work.efficiency / homework.max_efficiency * homework.eff_score + student_work.eff_score = format("%.2f", eff_score) + else + student_work.eff_score = 0 + end + elsif !compelete + student_work.compelete_status = 0 + end + student_work.final_score = format("%.2f", final_score.to_f) + score = student_work.final_score + student_work.eff_score - student_work.late_penalty + student_work.work_score = format("%.2f", score < 0 ? 0 : score.to_f) unless student_work.ultimate_score + student_work.save! + end +end + +# 用户评测时更新实训作业成绩 +def update_myshixun_work_score myshixun + ActiveRecord::Base.transaction do + student_works = myshixun.student_works + #logger.info("#############student_works_count: #{student_works.count}") + if student_works.count > 0 + student_works.each do |work| + homework = work.homework_common + member = Member.find_by_sql("select course_group_id from members where course_id = #{homework.course_id} and user_id = #{User.current.id}").first + #logger.info("#############member_course_group_id: #{member.try(:course_group_id)}") + setting_time = homework_group_setting homework, member.try(:course_group_id) + if setting_time.end_time.present? && (setting_time.end_time > Time.now || (homework.allow_late && !homework.course.is_end)) + #logger.info("#############setting_time: #{setting_time.end_time}") + + user_total_score = 0 + pass_consume_time = 0 + final_score = 0 + homework.homework_challenge_settings.each do |setting| + game = myshixun.games.where(:challenge_id => setting.challenge_id, :status => 2).first + unless game.nil? + pass_consume_time += (game.cost_time / 60.0).to_f + user_total_score += game.final_score.to_i < 0 ? 0 : game.challenge.score.to_i + adjust_score = work.challenge_work_scores.where(:challenge_id => setting.challenge_id).last + final_score += adjust_score.present? ? adjust_score.score : (homework.homework_detail_manual.answer_open_evaluation ? setting.score : (game.final_score >= 0 ? setting.score : 0)) + end + end + if work.work_status == 0 + is_complete = myshixun.is_complete? && (myshixun.done_time < setting_time.end_time) + work.work_status = setting_time.end_time > Time.now ? 1 : (is_complete ? 1 : 2) + work.late_penalty = setting_time.end_time > Time.now ? 0 : (is_complete ? 0 : homework.late_penalty) + work.commit_time = myshixun.created_at > setting_time.publish_time ? setting_time.publish_time : myshixun.created_at + work.myshixun_id = myshixun.id + end + + efficiency = (pass_consume_time == 0 ? 0 : Math.log((user_total_score / pass_consume_time.to_f) + 1.0)) + work.efficiency = format("%.2f", efficiency) + + games = myshixun.games.where(:challenge_id => homework.homework_challenge_settings.map(&:challenge_id)) + myshixun_endtime = games.select{|game| game.status == 2}.size == games.size ? games.map(&:end_time).max : nil + if myshixun_endtime.present? + min_efficiency_changed = min_efficiency_changed.present? ? min_efficiency_changed : false + work.compelete_status = 1 + work.cost_time = myshixun_endtime.to_i - setting_time.publish_time.to_i + + # 计算作品的效率分(已完成才计算) + if homework.work_efficiency + # 如果作业的最大效率值有变更则更新所有作品的效率分 + if homework.max_efficiency < work.efficiency + homework.max_efficiency = work.efficiency + homework.update_column("max_efficiency", homework.max_efficiency) + update_student_eff_score homework + end + eff_score = homework.max_efficiency == 0 ? 0 : work.efficiency / homework.max_efficiency * homework.eff_score + work.eff_score = format("%.2f", eff_score) + end + end + + work.update_time = Time.now + + # 为迁移的数据做特殊处理, 若分数小于当前通关分数则不更新 + work.final_score = final_score if work.final_score.nil? || final_score > work.final_score + score = work.final_score + work.eff_score - work.late_penalty + work.work_score = format("%.2f",(score < 0 ? 0 : score).to_f) unless work.ultimate_score + #logger.info("#############work_score: #{score}") + work.save! + end + end + end + end +end + +# 用户开启实训时更新作品状态 +def update_myshixun_work_status myshixun + student_works = StudentWork.find_by_sql("SELECT sw.* FROM student_works sw, homework_commons_shixuns hcs WHERE sw.user_id = #{User.current.id} AND sw.`homework_common_id` = hcs.`homework_common_id` AND hcs.`shixun_id` = #{myshixun.shixun_id} and sw.work_status = 0") + logger.info("#############student_works_count: #{student_works.count}") + if student_works.count > 0 + student_works.each do |work| + homework = work.homework_common + member = Member.find_by_sql("select course_group_id from members where course_id = #{homework.course_id} and user_id = #{User.current.id}").first + setting_time = homework_group_setting homework, member.try(:course_group_id) + if setting_time.end_time.present? && (setting_time.end_time > Time.now || (homework.allow_late && !homework.course.is_end)) + logger.info("#############setting_time: #{setting_time.end_time}") + work.work_status = setting_time.end_time > Time.now ? 1 : 2 + work.late_penalty = setting_time.end_time > Time.now ? 0 : homework.late_penalty + work.update_time = Time.now + work.commit_time = Time.now + work.myshixun_id = myshixun.id + work.save + end + end + end +end + +def quote_resource_bank resource, course + atta = Attachment.new(:filename => resource.filename, :disk_filename => resource.disk_filename, :filesize => resource.filesize, :digest => resource.digest, :downloads => 0, :is_publish => 0, + :author_id => User.current.id, :description => resource.description, :disk_directory => resource.disk_directory, :is_public => 0, :copy_from => resource.copy_from.nil? ? resource.id : resource.copy_from, + :quotes => 0, :resource_bank_id => resource.id, :created_on => Time.now, :content_type =>resource.content_type) + if course.attachments << atta + # 更新引用次数 + quotes = resource.quotes.to_i + 1 + resource.update_attribute(:quotes, quotes) + end +end + +def quote_homework_bank homework, course + ActiveRecord::Base.transaction do + new_homework = HomeworkCommon.new(:name => homework.name, :user_id => User.current.id, :description => homework.description, :homework_type => homework.homework_type, :late_penalty => 5, + :course_id => course.id, :teacher_priority => 1, :anonymous_comment => 1, :quotes => 0, :is_open => 0, :homework_bank_id => homework.id, :score_open => 1, + :anonymous_appeal => 0, :is_public => 0, :reference_answer => homework.reference_answer, :answer_public => 1, :allow_late => 1) + + new_homework.homework_detail_manual = HomeworkDetailManual.new + new_homework_detail_manual = new_homework.homework_detail_manual + new_homework_detail_manual.te_proportion = 1.0 + new_homework_detail_manual.ta_proportion = 0 + new_homework_detail_manual.comment_status = 0 + + new_homework_detail_manual.evaluation_num = 0 + new_homework_detail_manual.absence_penalty = 0 + + if new_homework.homework_type == 2 + new_homework.homework_detail_programing = HomeworkDetailPrograming.new + new_homework.homework_detail_programing.ta_proportion = 0 + new_homework.homework_detail_programing.language = homework.language + homework.homework_bank_tests.each_with_index do |homework_test| + new_homework.homework_tests << HomeworkTest.new( + input: homework_test.input, + output: homework_test.output + ) + end + homework.homework_bank_samples.each_with_index do |homework_test| + new_homework.homework_samples << HomeworkSample.new( + input: homework_test.input, + output: homework_test.output + ) + end + end + + if new_homework.homework_type == 3 + new_homework.homework_detail_group = HomeworkDetailGroup.new + new_homework.homework_detail_group.min_num = homework.min_num + new_homework.homework_detail_group.max_num = homework.max_num + new_homework.homework_detail_group.base_on_project = homework.base_on_project + end + + homework.attachments.each do |attachment| + att = attachment.copy + att.container_id = nil + att.container_type = nil + att.author_id = homework.user_id + att.copy_from = attachment.id + att.save + new_homework.attachments << att + end + + if new_homework.save + if new_homework.homework_type == 4 + HomeworkCommonsShixuns.create(:homework_common_id => new_homework.id, :shixun_id => homework.homework_bank_shixun.shixun_id) + end + new_homework_detail_manual.save if new_homework_detail_manual + new_homework.homework_detail_programing.save if new_homework.homework_detail_programing + new_homework.homework_detail_group.save if new_homework.homework_detail_group + create_works_list new_homework + + homework.update_column(:quotes, homework.quotes+1) + QuestionBank.where(:container_id => homework.id, :container_type => ["Common", "Shixun", "Group"]).update_all(:quotes => homework.quotes) + end + return new_homework + end +end + +def quote_exercise_bank exercise, course + ActiveRecord::Base.transaction do + new_exercise = Exercise.new(:exercise_name => exercise.name, :exercise_description => exercise.description, :user_id => User.current.id, :is_public => 0, + :exercise_status => 1, :show_result => 1, :course_id => course.id, :time => -1, :exercise_bank_id => exercise.id) + + exercise.exercise_bank_questions.each do |q| + option = { + :question_title => q[:question_title], + :question_type => q[:question_type] || 1, + :question_number => q[:question_number], + :question_score => q[:question_score], + :shixun_id => q[:shixun_id] + } + exercise_question = new_exercise.exercise_questions.new option + + if q.question_type != 5 + for i in 1..q.exercise_bank_choices.count + choice_option = { + :choice_position => i, + :choice_text => q.exercise_bank_choices[i-1][:choice_text] + } + exercise_question.exercise_choices.new choice_option + end + + for i in 1..q.exercise_bank_standard_answers.count + standard_answer_option = { + :exercise_choice_id => q.exercise_bank_standard_answers[i-1][:exercise_bank_choice_id], + :answer_text => q.exercise_bank_standard_answers[i-1][:answer_text] + } + exercise_question.exercise_standard_answers.new standard_answer_option + end + else + for i in 1..q.exercise_bank_shixun_challenges.count + challenge_option = { + :position => i, + :challenge_id => q.exercise_bank_shixun_challenges[i-1][:challenge_id], + :shixun_id => q.exercise_bank_shixun_challenges[i-1][:shixun_id], + :question_score => q.exercise_bank_shixun_challenges[i-1][:question_score] + } + exercise_question.exercise_shixun_challenges.new challenge_option + end + end + end + if new_exercise.save + create_exercises_list new_exercise + exercise.update_column(:quotes, exercise.quotes+1) + QuestionBank.where(:container_id => exercise.id, :container_type => "Exercise").update_all(:quotes => exercise.quotes) + end + return new_exercise + end +end + +def quote_poll_bank poll, course + ActiveRecord::Base.transaction do + new_poll = Poll.new(:polls_name => poll.name, :polls_description => poll.description, :user_id => User.current.id, :is_public => 0, + :polls_status => 1, :show_result => 1, :polls_type => 'Course', :course_id => course.id, :exercise_bank_id => poll.id) + + poll.exercise_bank_questions.each do |q| + option = { + :question_title => q[:question_title], + :question_type => q[:question_type] || 1, + :is_necessary => q[:is_necessary], + :question_number => q[:question_number], + :max_choices => q[:max_choices], + :min_choices => q[:min_choices] + } + poll_question = new_poll.poll_questions.new option + + for i in 1..q.exercise_bank_choices.count + choice_option = { + :answer_position => i, + :answer_text => q.exercise_bank_choices[i-1][:choice_text] + } + poll_question.poll_answers.new choice_option + end + end + if new_poll.save + create_polls_list new_poll + poll.update_column(:quotes, poll.quotes+1) + QuestionBank.where(:container_id => poll.id, :container_type => "Poll").update_all(:quotes => poll.quotes) + end + return new_poll + end +end + +def major_level_option + content = [] + option0 = [] + option0 << "选择课程所属专业层级" + option0 << 0 + option1 = [] + option1 << "专科" + option1 << 3 + option2 = [] + option2 << "本科" + option2 << 2 + option3 = [] + option3 << "研究生" + option3 << 1 + content << option0 + content << option1 + content << option2 + content << option3 + content +end + +def discipline_category_option major_level = 3 + content = [] + option0 = [] + option0 << "选择课程所属学科门类" + option0 << 0 + content << option0 + DisciplineCategory.where(:major_level => major_level).each do |dis| + option = [] + option << dis.name.to_s + option << dis.id + content << option + end + content +end + +def first_level_discipline_option disc_ca = 27 + content = [] + option0 = [] + option0 << "选择课程所属一级学科" + option0 << 0 + content << option0 + FirstLevelDiscipline.where(:discipline_category_id => disc_ca).each do |fir_dis| + option = [] + option << fir_dis.name.to_s + option << fir_dis.id + content << option + end + content +end + +def syllabus_major_option fir_dis = 213 + content = [] + option0 = [] + option0 << "选择课程所属专业" + option0 << 0 + content << option0 + Major.where(:first_level_discipline_id => fir_dis).each do |major| + option = [] + option << major.name.to_s + option << major.id + content << option + end + content +end + +def convert_to_char(str) + result = "" + length = str.length + unless str.nil? + if length === 1 + result += (str.to_i + 64).chr + return result + elsif length > 1 + for i in 0...length + result += (str[i].to_i + 64).chr + end + return result + end + end + return result +end + +def convert_to_chi_num num + result = "" + case num.to_i + when 1 + result = '一' + when 2 + result = '二' + when 3 + result = '三' + when 4 + result = '四' + when 5 + result = '五' + when 6 + result = '六' + when 7 + result = '七' + when 8 + result = '八' + when 9 + result = '九' + end + return result +end + +#根据条件过滤作业结果 +def search_work_member works,name + if name == "" + select_works = works + else + name = name.downcase + select_works = works.select{ |work| work.user.user_extensions[:student_id].to_s.downcase.include?(name) || (work.user[:lastname].to_s.downcase + work.user[:firstname].to_s.downcase).include?(name) + } + end + select_works +end + +# 作业的分班设置时间 +def homework_group_setting homework, group_id + setting = nil + if homework.homework_group_settings.where(:course_group_id => group_id).first + setting = homework.homework_group_settings.where(:course_group_id => group_id).first + else + setting = homework + end + setting +end + +# 试卷的分班设置时间 +def exercise_group_setting exercise, group + setting = nil + if exercise.exercise_group_settings.where(:course_group_id => group.try(:id)).first + setting = exercise.exercise_group_settings.where(:course_group_id => group.id).first + else + setting = exercise + end + setting +end + +# 问卷的分班设置时间 +def poll_group_setting poll, group + setting = nil + if poll.poll_group_settings.where(:course_group_id => group.try(:id)).first + setting = poll.poll_group_settings.where(:course_group_id => group.id).first + else + setting = poll + end + setting +end + +# 资源的分班设置时间 +def attacment_group_setting attachment, group + setting = nil + if attachment.attachment_group_settings.where(:course_group_id => group.try(:id)).first + setting = attachment.attachment_group_settings.where(:course_group_id => group.id).first + else + setting = attachment + end + setting +end + +#统计答题百分比,统计结果保留两位小数 +def statistics_result_percentage(e, t) + e = e.to_f + t = t.to_f + t == 0 ? 0 : format("%.1f", e*100/t) +end + +def subject_data subject + result = {} + subject_choices = 0 + subject_shixuns = 0 + subject_score = 0 + subject.stage_shixuns.each do |stage_shixun| + shixun = stage_shixun.shixun + subject_choices += shixun.challenges.where(:st => [1, 2]).count + subject_shixuns += shixun.challenges.where(:st => 0).count + subject_score += shixun.shixun_score + end + result[:subject_choices] = subject_choices + result[:subject_shixuns] = subject_shixuns + result[:subject_score] = subject_score + result +end + + +def tiding_url tiding + case tiding.container_type + when "ApplyUserAuthentication" + if tiding.tiding_type == "Apply" + tiding.container.auth_type == 1 ? identity_authentication_managements_path : professional_authentication_managements_path + else + tiding.container.auth_type == 1 ? authentication_account_path : professional_certification_account_path + end + when "CancelUserAuthentication" + authentication_account_path + when "CancelUserProCertification" + professional_certification_account_path + when "ApplyAddDepartment" + tiding.tiding_type == "Apply" ? depart_managements_path() : my_account_path() + when "ApplyAddSchools" + tiding.tiding_type == "Apply" ? unit_managements_path() : my_account_path() + when "ApplyAction" + tiding.tiding_type == "System" ? (tiding.parent_container_type == "ApplyShixun" ? shixun_path(Shixun.find(tiding.parent_container_id).identifier):(tiding.parent_container_type == "TrialAuthorization" ? user_path(tiding.user_id) : subject_path(tiding.parent_container_id))):(tiding.parent_container_type == "ApplyShixun" ? shixun_authorization_managements_path():(tiding.parent_container_type == "TrialAuthorization"? trial_authorization_managements_path(): subject_authorization_managements_path())) + when 'JoinCourse' + course_path(tiding.container_id, :type => "JoinCourse") + when 'StudentJoinCourse', 'DealCourse', 'TeacherJoinCourse' + course_path(tiding.container_id) + when 'Course', 'ArchiveCourse' + course_path(tiding.container_id) + when 'Shixun' + '/shixuns/' + tiding.container.identifier + when 'Subject' + '/paths/' + tiding.container_id.to_s + when 'JournalsForMessage' + case tiding.parent_container_type + when "Principal" + feedback_path(tiding.parent_container_id) + when "HomeworkCommon" + student_work_index_path(:homework => tiding.parent_container_id, :tab => 2) + when "GraduationTopic" + graduation_topic_path(tiding.parent_container_id, :tab => 2) + when "StudentWorksScore" + student_work_path(:id => tiding.container.try(:jour).try(:student_work_id)) + end + when 'Message' + board_message_path(tiding.container.board_id, tiding.parent_container_id) + when 'Memo' + forum_path(tiding.parent_container_id) + when 'Watcher' + user_path(tiding.trigger_user_id) + when 'PraiseTread' + try = tiding.parent_container_type.constantize + object = try.find(tiding.parent_container_id) + case tiding.parent_container_type + when "Challenge" + myshixun_id = Myshixun.where(:user_id => tiding.trigger_user_id, :shixun_id => Challenge.find(tiding.parent_container_id).shixun_id).first + myshixun_game_path(Game.where(:myshixun_id => myshixun_id.id, :challenge_id => tiding.parent_container_id).first, :myshixun_id => myshixun_id) + when "Discuss" + myshixun_game_path(object.user_game, :myshixun_id => object.user_myshixun) + when "Message" + object.parent.present? ? board_message_path(object.board_id, object.root_id) : board_message_path(object.board_id, object) + when "Memo" + object.parent.present? ? forum_path(object.root_id) : forum_path(object) + when "JournalsForMessage" + case object.jour_type + when "Principal" + feedback_path(object.jour_id) + when "HomeworkCommon" + student_work_index_path(:homework => object.jour_id, :tab => 2) + when "StudentWorksScore" + student_work_path(:id => object.try(:jour).try(:student_work_id)) + end + when "HomeworkCommon" + student_work_index_path(:homework => tiding.parent_container_id, :tab => 2) + when "Issue" + issue_path(tiding.parent_container_id) + when "Journal" + issue_path(object.journalized_id) + end + when 'Discuss' + shixun_discuss_shixun_path(tiding.container.dis) + when 'Grade' + user_grade_user_path(User.current) + when 'JoinProject' + project_path(tiding.container_id, :type => "applied_project") + when 'ReporterJoinProject', 'DealProject', 'ManagerJoinProject' + project_path(tiding.container_id) + when 'Poll' + case tiding.parent_container_type + when 'CommitPoll' + student_poll_list_poll_path(tiding.container, :tab => 2) + else + student_poll_list_poll_path(tiding.container) + end + when 'Exercise' + case tiding.parent_container_type + when 'CommitExercise', 'ExerciseScore' + show_student_result_exercise_path(tiding.container,:user_id => tiding.trigger_user_id) + else + student_exercise_list_exercise_path(tiding.container) + end + when 'StudentGraduationTopic', 'DealStudentTopicSelect' + graduation_topic_path(tiding.parent_container_id) + when 'GraduationTask' + graduation_task_path(tiding.container_id) + when 'GraduationWork' + graduation_work_path(tiding.container_id) + when 'GraduationWorkScore' + graduation_work_path(tiding.parent_container_id) + when 'HomeworkCommon' + case tiding.parent_container_type + when 'AnonymousCommentFail' + student_work_index_path(:homework => tiding.container_id, :tab => 4) + when 'HomeworkPublish' + student_work_index_path(:homework => tiding.container_id, :tab => 2) + when 'AnonymousAppeal' + work = tiding.container.student_works(:user_id => User.current.id).first + work.present? ? student_work_path(work.try(:id)) : "javascript:void(0)" + else + student_work_index_path(:homework => tiding.container_id) + end + when 'StudentWork' + student_work_path(tiding.container_id) + when 'StudentWorksScore', 'StudentWorksScoresAppeal' + student_work_path(tiding.parent_container_id) + when 'ChallengeWorkScore' + homework_common_path(tiding.container.try(:student_work).try(:homework_common_id)) + when 'SendMessage' + mirror_repository_managements_path + when 'Journal' + issue_path(tiding.parent_container_id) + when 'Issue' + issue_path(tiding.container_id) + when 'PullRequest' + project_pull_requests_path(tiding.parent_container_id) + when 'Department' + my_account_path + end +end + +def create_shixun_homework_cha_setting homework, shixun + if shixun.present? + sum_score = 0 + total_score = 100.0 - homework.eff_score + shixun.challenges.each_with_index do |challeng, index| + if index < shixun.challenges.length - 1 + score = ((total_score / shixun.challenges.length) * total_score).floor / total_score + sum_score += score + else + score = total_score - sum_score + end + HomeworkChallengeSetting.create(:homework_common_id => homework.id, :challenge_id => challeng.id, :shixun_id => shixun.id, :score => score) + end + end +end diff --git a/app/views/layouts/base_management.html.erb b/app/views/layouts/base_management.html.erb index 9d1d77c8..e038f1c2 100644 --- a/app/views/layouts/base_management.html.erb +++ b/app/views/layouts/base_management.html.erb @@ -113,9 +113,9 @@
  • 审批
      -
    • <%= link_to "实名认证", :controller => "managements", :action => "identity_authentication" %>
    • -
    • <%= link_to "职业认证", :controller => "managements", :action => "professional_authentication" %>
    • -
    • <%= link_to "试用授权", :controller => "managements", :action => "trial_authorization" %>
    • +
    • <%= link_to "实名认证", identity_authentication_managements_path %>
    • +
    • <%= link_to "职业认证", professional_authentication_managements_path %>
    • +
    • <%= link_to "试用授权", trial_authorization_managements_path %>
    • <%= link_to "部门审批", depart_managements_path %>
    • <%= link_to '单位审批', unit_managements_path %>
    • <%= link_to '实训发布', shixun_authorization_managements_path %>