From aabf1ee50f09904ecc1debe000300ba012c9a84b Mon Sep 17 00:00:00 2001 From: zhangxunhui Date: Tue, 31 Jan 2023 15:29:08 +0800 Subject: [PATCH 01/11] remove render_ok after creating pull request --- app/controllers/pull_requests_controller.rb | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/controllers/pull_requests_controller.rb b/app/controllers/pull_requests_controller.rb index 6c56f0213..a30fd4930 100644 --- a/app/controllers/pull_requests_controller.rb +++ b/app/controllers/pull_requests_controller.rb @@ -82,8 +82,6 @@ class PullRequestsController < ApplicationController if success_blockchain == false render_error("create pull request error: cannot save to blockchain") raise ActiveRecord::Rollback - else - render_ok end else render_error("create pull request error: #{@gitea_pull_request[:status]}") From 3c18d1ee9b08e460acb60eebc533d6aa8fc6dff8 Mon Sep 17 00:00:00 2001 From: zhangxunhui Date: Wed, 1 Feb 2023 14:45:04 +0800 Subject: [PATCH 02/11] remove duplicate render of journal --- app/controllers/journals_controller.rb | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/controllers/journals_controller.rb b/app/controllers/journals_controller.rb index ec5e523f9..029214f4c 100644 --- a/app/controllers/journals_controller.rb +++ b/app/controllers/journals_controller.rb @@ -55,8 +55,6 @@ class JournalsController < ApplicationController if success_blockchain == false normal_status(-1, "评论失败") raise ActiveRecord::Rollback - else - render json: {status: 0, message: "评论成功", id: journal.id} end render :json => { status: 0, message: "评论成功", id: journal.id} From 19e7fcaafacbe1a197f5d42c07461f0f96400bec Mon Sep 17 00:00:00 2001 From: zhangxunhui Date: Wed, 1 Feb 2023 14:47:56 +0800 Subject: [PATCH 03/11] add contribution_perc function --- app/controllers/users_controller.rb | 110 ++++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 2536ad6f3..ab75b78fd 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -81,6 +81,116 @@ class UsersController < ApplicationController @watchers = paginate(watchers) end + def contribution_perc + project_id = params[:project_id] + @project = Project.find(project_id) + user_id = params[:id] + @user = User.find(user_id) + # 获取所有行为对应的项目内记录总数和个人记录数 + features = { + "requirement" => {}, + "development" => {}, + "review" => {} + } + + def cal_perc(count_user, count_all) + (count_user * 1.0 / (count_all + 0.000000001)).round(5) + end + + # 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" => milestone_user * 1.0 / 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" => pr_user * 1.0 / 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 = value["all"] * 1.0 / count_1 + weights[category] = weights[category].merge({key => weight}) + end + end + categories.each do |category| + weight = counts[category] * 1.0 / count_all + weights[category] = weights[category].merge({"category_weight" => weight}) + end + return weights + end + + weights_categories = cal_weight(features) + scores = { + "final" => 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 + scores["final"] += weights_categories[category]["category_weight"] * category_score.round(4) + scores = scores.merge({category => category_score.round(4)}) + end + render json: { scores: scores } + end + def hovercard end From bbe8407311be60af9519569e28de090686f1410f Mon Sep 17 00:00:00 2001 From: zhangxunhui Date: Wed, 1 Feb 2023 14:48:10 +0800 Subject: [PATCH 04/11] add contribution percentage route --- config/routes.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/config/routes.rb b/config/routes.rb index d24929c0f..4305789c0 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -282,6 +282,7 @@ Rails.application.routes.draw do get :hovercard put :update_image get :get_image + post :contribution_perc # author: zxh, calculate the percentage of contributions for user in project end collection do post :following From c5314f7439665d0ab575a8bc459d0f7294f8b9be Mon Sep 17 00:00:00 2001 From: zhangxunhui Date: Thu, 2 Feb 2023 13:59:24 +0800 Subject: [PATCH 05/11] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E4=BA=86=E5=AF=B9?= =?UTF-8?q?=E5=8C=BA=E5=9D=97=E9=93=BE=E4=B8=8A=E4=BB=93=E5=BA=93=E5=9F=BA?= =?UTF-8?q?=E6=9C=AC=E4=BF=A1=E6=81=AF=E7=9A=84=E6=9F=A5=E8=AF=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/queries/blockchain/repo_basic_info.rb | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 app/queries/blockchain/repo_basic_info.rb diff --git a/app/queries/blockchain/repo_basic_info.rb b/app/queries/blockchain/repo_basic_info.rb new file mode 100644 index 000000000..716a67ba3 --- /dev/null +++ b/app/queries/blockchain/repo_basic_info.rb @@ -0,0 +1,17 @@ +class Blockchain::RepoBasicInfo < ApplicationQuery + + attr_reader :params, :is_current_admin_user + + def initialize(params) + @params = params + end + + def call + info = find_blockchain_repo_info(params[:project_id].to_s) + if info == false + return false + else + return info + end + end +end From ada6afa500c3afa00942f95b7731bca2b1fc10c1 Mon Sep 17 00:00:00 2001 From: zhangxunhui Date: Thu, 2 Feb 2023 14:00:13 +0800 Subject: [PATCH 06/11] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=BA=86contribution?= =?UTF-8?q?=5Fperc=E5=87=BD=E6=95=B0=EF=BC=8C=E6=B7=BB=E5=8A=A0=E4=BA=86?= =?UTF-8?q?=E5=AF=B9=E5=8C=BA=E5=9D=97=E9=93=BE=E7=A1=AE=E6=9D=83=E9=A1=B9?= =?UTF-8?q?=E7=9B=AE=E7=9A=84=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controllers/users_controller.rb | 191 +++++++++++++++------------- 1 file changed, 101 insertions(+), 90 deletions(-) diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index ab75b78fd..baa9ae826 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -86,107 +86,118 @@ class UsersController < ApplicationController @project = Project.find(project_id) user_id = params[:id] @user = User.find(user_id) - # 获取所有行为对应的项目内记录总数和个人记录数 - features = { - "requirement" => {}, - "development" => {}, - "review" => {} - } def cal_perc(count_user, count_all) (count_user * 1.0 / (count_all + 0.000000001)).round(5) end - # 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" => milestone_user * 1.0 / 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" => pr_user * 1.0 / 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"] + if @project.use_blockchain == true or @project.use_blockchain == 1 + balance_user = Blockchain::BalanceQueryOneProject.call({"user_id": user_id, "project_id": project_id})[:balance] + balance_all = Blockchain::RepoBasicInfo.call({"project_id": project_id})["cur_supply"] + scores = { + "final" => cal_perc(balance_user, balance_all), + "blockchain" => true + } + else + # 获取所有行为对应的项目内记录总数和个人记录数 + features = { + "requirement" => {}, + "development" => {}, + "review" => {} + } - 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 + # 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"] - 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 = value["all"] * 1.0 / count_1 - weights[category] = weights[category].merge({key => weight}) + 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 - categories.each do |category| - weight = counts[category] * 1.0 / count_all - weights[category] = weights[category].merge({"category_weight" => weight}) - end - return weights - end - weights_categories = cal_weight(features) - scores = { - "final" => 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"] + 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) + scores = { + "final" => 0.0, + "blockchain" => false + } + 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 + scores["final"] += weights_categories[category]["category_weight"] * category_score.round(4) + scores = scores.merge({category => category_score.round(4)}) end - scores["final"] += weights_categories[category]["category_weight"] * category_score.round(4) - scores = scores.merge({category => category_score.round(4)}) end render json: { scores: scores } end From c5ee0e54001938e74b118a77ace9cb6748efae82 Mon Sep 17 00:00:00 2001 From: zhangxunhui Date: Thu, 2 Feb 2023 16:55:25 +0800 Subject: [PATCH 07/11] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E4=BA=86=E9=92=88?= =?UTF-8?q?=E5=AF=B9=E9=A1=B9=E7=9B=AE=E8=B4=A1=E7=8C=AE=E5=BA=A6=E9=87=8F?= =?UTF-8?q?=E7=9A=84hover=20json=E8=AF=B7=E6=B1=82=E6=A8=A1=E6=9D=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/views/users/hovercard4proj.json.jbuilder | 21 ++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 app/views/users/hovercard4proj.json.jbuilder diff --git a/app/views/users/hovercard4proj.json.jbuilder b/app/views/users/hovercard4proj.json.jbuilder new file mode 100644 index 000000000..aba904fe5 --- /dev/null +++ b/app/views/users/hovercard4proj.json.jbuilder @@ -0,0 +1,21 @@ +json.id @user.id +json.login @user.login +json.name @user.full_name +json.location @user.location +json.image_url url_to_avatar(@user) +json.url "#{request.base_url }/#{@user.login}" +json.followers_count @user.followers_count +json.followers_url "#{base_url}/#{@user.login}/fan_users" +json.following_count @user.following_count +json.following_url "#{base_url}/#{@user.login}/watchers" +json.projects_count @user.projects_count +json.projects_url "#{base_url}/#{@user.login}" +json.projects_count @user.projects_count +json.is_watch current_user&.watched?(@user) +json.contribution_perc @user.contribution_perc +json.organizations @user.organizations do |organization| + json.login organization.login + json.name organization.real_name + json.image_url url_to_avatar(organization) + json.url "#{base_url}/#{organization.login}" +end \ No newline at end of file From efc96f34678662abced6376d7db0ce4ce546b58f Mon Sep 17 00:00:00 2001 From: zhangxunhui Date: Thu, 2 Feb 2023 16:56:04 +0800 Subject: [PATCH 08/11] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=AF=B9hovercard4proj?= =?UTF-8?q?=E7=9A=84=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controllers/users_controller.rb | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index baa9ae826..1cc3a5045 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -2,8 +2,8 @@ class UsersController < ApplicationController include ApplicationHelper include Ci::DbConnectable - before_action :load_user, only: [:show, :homepage_info, :sync_token, :sync_gitea_pwd, :projects, :watch_users, :fan_users, :hovercard] - before_action :check_user_exist, only: [:show, :homepage_info,:projects, :watch_users, :fan_users, :hovercard] + before_action :load_user, only: [:show, :homepage_info, :sync_token, :sync_gitea_pwd, :projects, :watch_users, :fan_users, :hovercard, :hovercard4proj] + before_action :check_user_exist, only: [:show, :homepage_info,:projects, :watch_users, :fan_users, :hovercard, :hovercard4proj] before_action :require_login, only: %i[me sync_user_info] before_action :connect_to_ci_db, only: [:get_user_info] before_action :convert_image!, only: [:update, :update_image] @@ -205,6 +205,10 @@ class UsersController < ApplicationController def hovercard end + # author: zxh, 查询贡献者的贡献度 + def hovercard4proj + end + def update return render_not_found unless @user = User.find_by(login: params[:id]) || User.find_by_id(params[:id]) return render_forbidden unless User.current.logged? && (current_user&.admin? || current_user.id == @user.id) From 1da1c51ba73daa89a62c0b5022b675d5357138f0 Mon Sep 17 00:00:00 2001 From: zhangxunhui Date: Thu, 2 Feb 2023 16:59:10 +0800 Subject: [PATCH 09/11] =?UTF-8?q?watchable=E7=94=A8=E6=88=B7=E8=B4=A1?= =?UTF-8?q?=E7=8C=AE=E5=BA=A6=E7=9A=84=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/models/concerns/watchable.rb | 205 ++++++++++++++++++++++++------- 1 file changed, 160 insertions(+), 45 deletions(-) diff --git a/app/models/concerns/watchable.rb b/app/models/concerns/watchable.rb index 008d382f3..e97c6cc2a 100644 --- a/app/models/concerns/watchable.rb +++ b/app/models/concerns/watchable.rb @@ -1,45 +1,160 @@ -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 followers - watcher_users - end - - def followers_count - followers.size - end - - module ClassMethods - end -end +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 contribution_perc + project_name = params[:project_name] + user_login = params[:id] + @project = Project.find_by_name(project_name) + @user = User.find_by_login(user_login) + + 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] + 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 From 18a900a07e9e33793424784e24ce7e3375cbb34e Mon Sep 17 00:00:00 2001 From: zhangxunhui Date: Thu, 2 Feb 2023 17:00:12 +0800 Subject: [PATCH 10/11] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E4=BA=86=E5=AF=B9contr?= =?UTF-8?q?ibution=20perc=E7=9A=84=E8=B7=AF=E7=94=B1=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/routes.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/routes.rb b/config/routes.rb index 4305789c0..ea16571ec 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -280,9 +280,9 @@ Rails.application.routes.draw do get :fan_users put :update_sponsor_description get :hovercard + get :hovercard4proj # author: zxh, 获取用户对项目的贡献情况 put :update_image get :get_image - post :contribution_perc # author: zxh, calculate the percentage of contributions for user in project end collection do post :following From 2f6c5686881d510a8327212708bb28acdc604147 Mon Sep 17 00:00:00 2001 From: zhangxunhui Date: Thu, 2 Feb 2023 17:00:49 +0800 Subject: [PATCH 11/11] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E4=BA=86=E5=AF=B9?= =?UTF-8?q?=E5=8C=BA=E5=9D=97=E9=93=BE=E9=A1=B9=E7=9B=AE=E5=9F=BA=E6=9C=AC?= =?UTF-8?q?=E4=BF=A1=E6=81=AF=E7=9A=84=E6=9F=A5=E8=AF=A2=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/queries/application_query.rb | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/app/queries/application_query.rb b/app/queries/application_query.rb index 5029da759..5fd13055d 100644 --- a/app/queries/application_query.rb +++ b/app/queries/application_query.rb @@ -63,4 +63,14 @@ class ApplicationQuery return resp_body end + # query the basic info of a repository + def find_blockchain_repo_info(project_id) + param = { + "request-type": "query repo basic info", + "token_name": project_id.to_s + }.to_json + resp_body = invoke_blockchain_api(Blockchain.blockchain_config[:api_url], param) + return resp_body + end + end \ No newline at end of file