module Watchable extend ActiveSupport::Concern included do has_many :watchers, as: :watchable, dependent: :destroy has_many :watcher_users, through: :watchers, source: :user, validate: false scope :watched_by, -> (user_id) { includes(:watchers).where(watchers: { user_id: user_id }) } scope :following, -> (user_id) { watched_by(user_id) } end def watched?(watchable) watchable.watchers.exists?(user: self) end def watch!(watchable) watchable.watchers.create!(user: self, created_at: Time.current) end def unwatch!(watchable) obj = watchable.watchers.find_by(user: self) obj.destroy! if obj.present? end # 我正在关注的、我追随的 def following User.following(self.id) end def following_count following.size end def simple_contribution_perc(project, perc=nil) @project = project @user = self def cal_perc(count_user, count_all) (count_user * 1.0 / (count_all + 0.000000001)).round(5) end if Site.has_blockchain? && (@project['use_blockchain'] == true or @project['use_blockchain'] == 1) && @user.id.present? balance_user = Blockchain::BalanceQueryOneProject.call({"user_id": @user.id, "project_id": @project.id}) balance_all = Blockchain::RepoBasicInfo.call({"project_id": @project.id})["cur_supply"] score = cal_perc(balance_user, balance_all) score = (score * 100).round(1).to_s + "%" else score = perc end score end def contribution_perc(project) @project = project @user = self def cal_perc(count_user, count_all) (count_user * 1.0 / (count_all + 0.000000001)).round(5) end if @project['use_blockchain'] == true or @project['use_blockchain'] == 1 balance_user = Blockchain::BalanceQueryOneProject.call({"user_id": @user.id, "project_id": @project.id}) balance_all = Blockchain::RepoBasicInfo.call({"project_id": @project.id})["cur_supply"] score = cal_perc(balance_user, balance_all) else # 获取所有行为对应的项目内记录总数和个人记录数 features = { "requirement" => {}, "development" => {}, "review" => {} } # 1. issue创建 issues = Issue.where(project_id: @project.id, issue_classify: 'issue') issue_all = issues.count issue_user = issues.where(author_id: @user.id).count features["requirement"] = features["requirement"].merge({"issue" => {"all" => issue_all, "perc" => cal_perc(issue_user, issue_all)}}) # 2. 里程碑创建 milestones = Version.where(project_id: @project.id) milestone_all = milestones.count milestone_user = milestones.where(user_id: @user.id).count features["requirement"] = features["requirement"].merge({"milestone" => {"all" => milestone_all, "perc" => cal_perc(milestone_user, milestone_all)}}) # 3. issue评论 issue_comments = Journal.joins("INNER JOIN issues on journals.journalized_id=issues.id").where("issues.project_id=#{@project.id} and journalized_type='Issue' and issues.issue_classify='issue'") issue_comment_all = issue_comments.count issue_comment_user = issue_comments.where("journals.user_id=#{@user.id}").count features["requirement"] = features["requirement"].merge({"issue_comment" => {"all" => issue_comment_all, "perc" => cal_perc(issue_comment_user, issue_comment_all)}}) # 4. 合并请求 prs = PullRequest.where(project_id: @project.id) pr_all = prs.count pr_user = prs.where(user_id: @user.id).count features["development"] = features["development"].merge({"pr" => {"all" => pr_all, "perc" => cal_perc(pr_user, pr_all)}}) # 5. pr评论 pr_comments = Journal.joins("INNER JOIN issues on journals.journalized_id=issues.id").where("issues.project_id=#{@project.id} and journalized_type='Issue' and issues.issue_classify='pull_request'") pr_comment_all = pr_comments.count pr_comment_user = pr_comments.where("journals.user_id=#{@user.id}").count features["review"] = features["review"].merge({"pr_comment" => {"all" => pr_comment_all, "perc" => cal_perc(pr_comment_user, pr_comment_all)}}) # 6. 代码行评论 line_comments = Journal.joins("INNER JOIN pull_requests on journals.journalized_id=pull_requests.id").where("pull_requests.project_id=#{@project.id} and journalized_type='PullRequest'") line_comment_all = line_comments.count line_comment_user = line_comments.where("journals.user_id=#{@user.id}").count features["review"] = features["review"].merge({"line_comment" => {"all" => line_comment_all, "perc" => cal_perc(line_comment_user, line_comment_all)}}) # 7. 代码行、commit贡献统计 code_contributions = Api::V1::Projects::CodeStats::ListService.call(@project, {ref: nil}) commit_all = code_contributions["commit_count"] addition_all = code_contributions["additions"] deletion_all = code_contributions["deletions"] commit_user = 0 addition_user = 0 deletion_user = 0 code_contributions["authors"].each do |author| if author["name"] == @user.login commit_user = author["commits"] addition_user = author["additions"] deletion_user = author["deletions"] end end features["development"] = features["development"].merge({"commit" => {"all" => commit_all, "perc" => cal_perc(commit_user, commit_all)}}) features["development"] = features["development"].merge({"addition" => {"all" => addition_all, "perc" => cal_perc(addition_user, addition_all)}}) features["development"] = features["development"].merge({"deletion" => {"all" => deletion_all, "perc" => cal_perc(deletion_user, deletion_all)}}) def cal_weight(features) weights = {} # 计算每一项的权重 categories = [] features.each do |key, _| categories << key weights[key] = Hash.new end count_all = 0 counts = {} categories.each do |category| count_1 = 0 features[category].each do |_, value| count_1 += value["all"] end count_all += count_1 counts[category] = count_1 features[category].each do |key, value| weight = cal_perc(value["all"], count_1) weights[category] = weights[category].merge({key => weight}) end end categories.each do |category| weight = cal_perc(counts[category], count_all) weights[category] = weights[category].merge({"category_weight" => weight}) end return weights end weights_categories = cal_weight(features) score = 0.0 features.each do |category, value_1| category_score = 0.0 value_1.each do |action, value_2| category_score += weights_categories[category][action] * value_2["perc"] end score += weights_categories[category]["category_weight"] * category_score.round(4) end end score (score * 100).round(1).to_s + "%" end # 关注我的、我的粉丝、我的追随者 def followers watcher_users end def followers_count followers.size end module ClassMethods end end