From 281ec379701a357f14f983ff990d1d29f45b20fe Mon Sep 17 00:00:00 2001 From: xiaochong0302 Date: Wed, 30 Dec 2020 17:49:32 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E8=AF=BE=E7=A8=8B=E7=BB=BC?= =?UTF-8?q?=E5=90=88=E8=AF=84=E5=88=86=E7=AE=97=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/Console/Tasks/SyncCourseScoreTask.php | 44 ++++++++++++ app/Models/Course.php | 4 ++ app/Services/CourseStat.php | 85 ++++++++++++++++++++++- app/Services/Sync/CourseScore.php | 33 +++++++++ scheduler.php | 3 + 5 files changed, 166 insertions(+), 3 deletions(-) create mode 100644 app/Console/Tasks/SyncCourseScoreTask.php create mode 100644 app/Services/Sync/CourseScore.php diff --git a/app/Console/Tasks/SyncCourseScoreTask.php b/app/Console/Tasks/SyncCourseScoreTask.php new file mode 100644 index 00000000..3a789633 --- /dev/null +++ b/app/Console/Tasks/SyncCourseScoreTask.php @@ -0,0 +1,44 @@ +getRedis(); + + $key = $this->getSyncKey(); + + $courseIds = $redis->sRandMember($key, 1000); + + if (!$courseIds) return; + + $courseRepo = new CourseRepo(); + + $courses = $courseRepo->findByIds($courseIds); + + if ($courses->count() == 0) return; + + $statService = new CourseStatService(); + + foreach ($courses as $course) { + $statService->updateScore($course->id); + } + + $redis->sRem($key, ...$courseIds); + } + + protected function getSyncKey() + { + $sync = new CourseScoreSync(); + + return $sync->getSyncKey(); + } + +} diff --git a/app/Models/Course.php b/app/Models/Course.php index 282da552..474ae0d8 100644 --- a/app/Models/Course.php +++ b/app/Models/Course.php @@ -4,6 +4,7 @@ namespace App\Models; use App\Caches\MaxCourseId as MaxCourseIdCache; use App\Services\Sync\CourseIndex as CourseIndexSync; +use App\Services\Sync\CourseScore as CourseScoreSync; use Phalcon\Mvc\Model\Behavior\SoftDelete; use Phalcon\Text; @@ -309,6 +310,9 @@ class Course extends Model if (time() - $this->update_time > 3 * 3600) { $sync = new CourseIndexSync(); $sync->addItem($this->id); + + $sync = new CourseScoreSync(); + $sync->addItem($this->id); } if (Text::startsWith($this->cover, 'http')) { diff --git a/app/Services/CourseStat.php b/app/Services/CourseStat.php index b5195e95..35639b3d 100644 --- a/app/Services/CourseStat.php +++ b/app/Services/CourseStat.php @@ -2,6 +2,7 @@ namespace App\Services; +use App\Models\Course as CourseModel; use App\Repos\Course as CourseRepo; use App\Repos\CourseRating as CourseRatingRepo; @@ -58,9 +59,19 @@ class CourseStat extends Service public function updateScore($courseId) { - /** - * @todo 计算综合评分 - */ + $courseRepo = new CourseRepo(); + + $course = $courseRepo->findById($courseId); + + if ($course->market_price == 0) { + $score = $this->calculateFreeCourseScore($course); + } else { + $score = $this->calculateChargeCourseScore($course); + } + + $course->score = $score; + + $course->update(); } public function updateReadAttrs($courseId) @@ -181,4 +192,72 @@ class CourseStat extends Service $course->update(['attrs' => $attrs]); } + protected function calculateFreeCourseScore(CourseModel $course) + { + $weight = [ + 'factor1' => 0.1, + 'factor2' => 0.25, + 'factor3' => 0.2, + 'factor4' => 0.1, + 'factor5' => 0.25, + 'factor6' => 0.1, + ]; + + return $this->calculateCourseScore($course, $weight); + } + + protected function calculateChargeCourseScore(CourseModel $course) + { + $weight = [ + 'factor1' => 0.1, + 'factor2' => 0.3, + 'factor3' => 0.15, + 'factor4' => 0.15, + 'factor5' => 0.2, + 'factor6' => 0.1, + ]; + + return $this->calculateCourseScore($course, $weight); + } + + protected function calculateCourseScore(CourseModel $course, $weight) + { + $items = [ + 'factor1' => 0.0, + 'factor2' => 0.0, + 'factor3' => 0.0, + 'factor4' => 0.0, + 'factor5' => 0.0, + 'factor6' => 0.0, + ]; + + $items['factor1'] = ($course->featured == 1 ? 1 : 0) * 10 * $weight['factor1']; + + if ($course->user_count > 0) { + $items['factor2'] = log($course->user_count) * $weight['factor2']; + } + + if ($course->favorite_count > 0) { + $items['factor3'] = log($course->favorite_count) * $weight['factor3']; + } + + if ($course->consult_count > 0) { + $items['factor4'] = log($course->consult_count) * $weight['factor4']; + } + + if ($course->review_count > 0 && $course->rating > 0) { + $items['factor5'] = log($course->review_count * $course->rating) * $weight['factor5']; + } + + $sumCount = $course->lesson_count + $course->package_count + $course->resource_count; + + if ($sumCount > 0) { + $items['factor6'] = log($sumCount) * $weight['factor6']; + } + + $score = array_sum($items) / log(time() - $course->create_time); + + return round($score, 4); + } + } diff --git a/app/Services/Sync/CourseScore.php b/app/Services/Sync/CourseScore.php new file mode 100644 index 00000000..506d27b8 --- /dev/null +++ b/app/Services/Sync/CourseScore.php @@ -0,0 +1,33 @@ +getRedis(); + + $key = $this->getSyncKey(); + + $redis->sAdd($key, $courseId); + + if ($redis->sCard($key) == 1) { + $redis->expire($key, $this->lifetime); + } + } + + public function getSyncKey() + { + return 'sync_course_score'; + } + +} diff --git a/scheduler.php b/scheduler.php index b1175a1b..2424b002 100644 --- a/scheduler.php +++ b/scheduler.php @@ -40,6 +40,9 @@ $scheduler->php($script, $bin, ['--task' => 'sync_group_index', '--action' => 'm $scheduler->php($script, $bin, ['--task' => 'sync_user_index', '--action' => 'main']) ->hourly(23); +$scheduler->php($script, $bin, ['--task' => 'sync_course_score', '--action' => 'main']) + ->hourly(29); + $scheduler->php($script, $bin, ['--task' => 'clean_log', '--action' => 'main']) ->daily(3, 3);