diff --git a/app/controllers/admins/project_evaluation_controller.rb b/app/controllers/admins/project_evaluation_controller.rb new file mode 100644 index 00000000..0745ddc6 --- /dev/null +++ b/app/controllers/admins/project_evaluation_controller.rb @@ -0,0 +1,33 @@ +class Admins::ProjectEvaluationController < Admins::BaseController + def update + Project.where(is_public: 1, id: Repository.pluck(:project_id)).find_each do |project| + ProjectEvaluation.update_raw_scores(project) + end + ProjectEvaluation.update_normalized_scores + + def evaluate_and_update(interval) + ProjectEvaluationTop.top_projects_selection(interval) + ProjectEvaluation.update_scores_by_interval(interval) + end + + current_date = Date.today + + if current_date.wday == 1 + evaluate_and_update(:weekly) + end + + if current_date.day == 1 + evaluate_and_update(:monthly) + end + + if current_date.day == 1 && [1, 4, 7, 10].include?(current_date.month) + evaluate_and_update(:quarterly) + end + + if current_date.yday == 1 + evaluate_and_update(:yearly) + end + + render_ok() + end +end diff --git a/app/models/project_evaluation.rb b/app/models/project_evaluation.rb index ab40ecb8..42f655c0 100644 --- a/app/models/project_evaluation.rb +++ b/app/models/project_evaluation.rb @@ -161,4 +161,9 @@ class ProjectEvaluation < ApplicationRecord evaluation.save end end + + def self.update_scores_by_interval(interval) + score_column = "#{interval}_score" + ProjectEvaluation.where.not(score: nil).update_all("#{score_column} = score") + end end diff --git a/app/models/project_evaluation_top.rb b/app/models/project_evaluation_top.rb new file mode 100644 index 00000000..783ac27f --- /dev/null +++ b/app/models/project_evaluation_top.rb @@ -0,0 +1,57 @@ +# == Schema Information +# +# Table name: project_evaluations_tops +# +# id :integer not null, primary key +# project_id :integer +# time_interval :integer +# previous_score :float(24) default("0") +# current_score :float(24) default("0") +# evaluation_period :integer +# created_at :datetime not null +# updated_at :datetime not null +# +# Indexes +# +# index_project_evaluations_tops_on_evaluation_period (evaluation_period) +# index_project_evaluations_tops_on_project_id (project_id) +# index_project_evaluations_tops_on_time_interval (time_interval) +# + +class ProjectEvaluationTop < ApplicationRecord + self.table_name = "project_evaluations_tops" + belongs_to :project + + enum time_interval: { + weekly: 0, + monthly: 1, + quarterly: 2, + yearly: 3, + } + + def self.top_projects_selection(time_interval) + max_evaluation_period = ProjectEvaluationTop + .where(time_interval: time_interval) + .maximum(:evaluation_period).to_i + last_evaluation = ProjectEvaluationTop + .where(time_interval: time_interval, evaluation_period: max_evaluation_period) + .first + return if last_evaluation&.created_at&.to_date == Date.today + + score_column = "#{time_interval}_score" + + selected_projects = ProjectEvaluation.where.not(score_column.to_sym => nil) + .order(Arel.sql("score - #{score_column} DESC")) + .limit(100) + + selected_projects.each do |project_evaluation| + ProjectEvaluationTop.create!( + project: project_evaluation.project, + time_interval: time_interval, + previous_score: project_evaluation.send(score_column), + current_score: project_evaluation.score, + evaluation_period: max_evaluation_period + 1, + ) + end + end +end diff --git a/config/routes.rb b/config/routes.rb index f8bc66b5..bf1fbfad 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -800,6 +800,12 @@ Rails.application.routes.draw do resources :sites resources :edu_settings resources :project_languages + resources :project_evaluation, only: [] do + collection do + put :update + end + end + resources :project_categories resources :project_licenses resources :project_ignores diff --git a/db/migrate/20230814091000_add_time_based_scores_to_project_evaluations.rb b/db/migrate/20230814091000_add_time_based_scores_to_project_evaluations.rb new file mode 100644 index 00000000..9fc84493 --- /dev/null +++ b/db/migrate/20230814091000_add_time_based_scores_to_project_evaluations.rb @@ -0,0 +1,11 @@ +# encoding: utf-8 +class AddTimeBasedScoresToProjectEvaluations < ActiveRecord::Migration[5.2] + def change + change_table :project_evaluations do |t| + t.float :weekly_score, comment: "每周分数" + t.float :monthly_score, comment: "每月分数" + t.float :quarterly_score, comment: "每季度分数" + t.float :yearly_score, comment: "每年分数" + end + end +end diff --git a/db/migrate/20230814091001_create_project_evaluation_tops.rb b/db/migrate/20230814091001_create_project_evaluation_tops.rb new file mode 100644 index 00000000..57afc57d --- /dev/null +++ b/db/migrate/20230814091001_create_project_evaluation_tops.rb @@ -0,0 +1,16 @@ +class CreateProjectEvaluationTops < ActiveRecord::Migration[5.2] + def change + create_table :project_evaluations_tops do |t| + t.integer :project_id, foreign_key: true, index: true + t.column :time_interval, :integer, comment: "时间间隔,0: weekly, 1: monthly, 2: quarterly, 3: yearly" + t.float :previous_score, default: 0, comment: "上次得分" + t.float :current_score, default: 0, comment: "本次得分" + t.integer :evaluation_period, comment: "评选期数" + t.timestamps + end + + add_index :project_evaluations_tops, :evaluation_period, name: "index_project_evaluations_tops_on_evaluation_period" + add_index :project_evaluations_tops, :time_interval, name: "index_project_evaluations_tops_on_time_interval" + add_foreign_key :project_evaluations_tops, :projects, column: :project_id + end +end