1493 lines
60 KiB
PHP
1493 lines
60 KiB
PHP
<?php
|
||
|
||
namespace App\Services;
|
||
|
||
use App\Models\Match\CityGps;
|
||
use App\Models\Match\Profile;
|
||
use App\Models\Match\Progresses;
|
||
use App\Models\Match\RecommendLinking;
|
||
use App\Models\Match\RecommendLinkingV2;
|
||
use App\Models\Match\Request;
|
||
use App\Models\Match\SBlacklist;
|
||
use App\Utils\Http;
|
||
use http\Exception;
|
||
use Illuminate\Support\Facades\Log;
|
||
use Illuminate\Support\Facades\Redis;
|
||
use Overtrue\Pinyin\Pinyin;
|
||
|
||
ini_set('memory_limit','1024M');
|
||
ini_set('max_execution_time', '0');
|
||
|
||
class UserMatchService
|
||
{
|
||
const WORKER_USER_ID_LIST = [
|
||
1, 625, 898, 61850, 42343, 48594, 49091, 49819, 647, 58701, 60889, 43020, 60744,
|
||
81685, 85172, 76429, 82400, 59078, 85037, 8163, 75247, 79675, 86159, 94076, 3480,
|
||
8771, 49408, 52958, 58290, 61848, 70533, 70535, 70537, 70538, 74993, 86029, 93259,
|
||
97623, 97733, 11800
|
||
];
|
||
//偏好要求字段
|
||
public const prefer_attrs = [
|
||
'min_age', 'max_age', 'min_height', 'max_height', 'is_same_city', 'is_same_resident_province'
|
||
];
|
||
|
||
public const degree = [
|
||
'其他' => 0, '小学' => 1, '初中' => 2, '初中及初中以下' => 2, '中专' => 4, '高中' => 4,
|
||
'高中/中专' => 4, '大专' => 5, '专科' => 5, '本科' => 6, '硕士' => 7, '硕士以上' => 7,'博士' => 8,
|
||
];
|
||
public static $static_ai_users;
|
||
public static $static_ai_reviews;
|
||
public static $static_ai_browses;
|
||
public static $static_city_gps;
|
||
public static $static_other_city;
|
||
public static $static_city_pin_yin;
|
||
|
||
public static $static_preview;
|
||
public static $static_browse;
|
||
public static $static_black_list;
|
||
public static $static_user_except;
|
||
|
||
/**
|
||
* 产生毫秒级的时间
|
||
* @return float
|
||
*/
|
||
private function micro_time_float(): float
|
||
{
|
||
list($microsecond, $second) = explode(" ", microtime());
|
||
return ((float)$microsecond + (float)$second);
|
||
}
|
||
|
||
/**
|
||
* 用户初始化文件
|
||
* @param null $new_user_id_list
|
||
* @return bool
|
||
*/
|
||
public function initUser(){
|
||
$system_black_ids = SBlacklist::whereNull('deleted_at')->pluck('user_id');
|
||
$profiles = Profile::with('member', 'match', 'blacklists', 'requests', 'friends', 'dislikes', 'previews', 'browses')
|
||
->withCount('photos')->whereNotNull('belief')->whereNotNull('sex')
|
||
->whereNotNull('province')->whereNotNull('city')/*->whereNotNull('state')*/
|
||
->whereNotIn('user_id', $system_black_ids->toArray())
|
||
->wherehas('member', function ($sql) {
|
||
$sql->where('hidden_profile', 'NONE')->where('sex', '>', 0);
|
||
});//->orderByDesc('info_complete_score');
|
||
//Log::notice('[initUser] load all auth user tables from mysql, on:' . (self::micro_time_float() - $start1));
|
||
$send_female_ids = [];
|
||
$send_male_ids = [];
|
||
$receive_user_list = [];
|
||
$receive_female_ids = [];
|
||
$receive_male_ids = [];
|
||
$worker_female_ids = [];
|
||
$worker_male_ids = [];
|
||
$total_user = $profiles->count();
|
||
$current_user = 0;
|
||
$profiles->chunk(1000, function ($profiles) use (
|
||
&$send_female_ids, &$send_male_ids, &$receive_user_list, $total_user, &$current_user,
|
||
$system_black_ids, &$receive_female_ids, &$receive_male_ids, &$worker_female_ids, &$worker_male_ids
|
||
) {
|
||
$i = 0;
|
||
foreach ($profiles as $profile) {
|
||
$i++;
|
||
$id = $profile->user_id;
|
||
$member = $profile->member;
|
||
if (empty($member->sex) || $member->sex < 1 || $profile->sex != $member->sex) {
|
||
error_log('[initUser] 出错 ID = ' . $id . ' 性别异常,跳过.');
|
||
Log::warning('[initUser] 出错 ID = ' . $id . ' 性别异常,跳过.');
|
||
continue;
|
||
}
|
||
/**
|
||
if (empty($member->belief) || $profile->belief != $member->belief) {
|
||
error_log('[initUser] 出错 ID = ' . $id . ' 信仰异常,跳过.');
|
||
Log::warning('[initUser] 出错 ID = ' . $id . ' 信仰异常,跳过.');
|
||
continue;
|
||
}
|
||
* */
|
||
$user = [];
|
||
$user['id'] = $id;
|
||
//profile
|
||
$user['birthday'] = $profile->birthday;
|
||
$user['belief'] = $profile->belief;
|
||
$user['province'] = $profile->province;
|
||
$user['city'] = $profile->city;
|
||
$user['state'] = $profile->state;
|
||
$user['weight'] = $profile->weight;
|
||
$user['stature'] = $profile->stature;
|
||
$user['stature'] = $profile->stature;
|
||
$user['resident_province'] = $profile->resident_province;
|
||
$user['resident_city'] = $profile->resident_city;
|
||
$user['degree'] = $profile->degree;
|
||
//like setting
|
||
$user['max_age'] = $profile->max_age;
|
||
$user['min_age'] = $profile->min_age;
|
||
$user['min_height'] = $profile->min_height;
|
||
$user['max_height'] = $profile->max_height;
|
||
$user['city_claim'] = $profile->city_claim;
|
||
$user['city_list_claim'] = $profile->city_list_claim;
|
||
$user['hometown_claim'] = $profile->hometown_claim;
|
||
$user['approve_claim'] = $profile->approve_claim;
|
||
$user['show_score'] = strlen($profile->introduction) + strlen($profile->ideal_mate);
|
||
$user['photos_count'] = $profile->photos_count;
|
||
if (isset($profile->match) && $profile->match->score > 70) {
|
||
$user['is_match'] = 1;
|
||
} else {
|
||
$user['is_match'] = 0;
|
||
}
|
||
if (isset($member->sex)) {
|
||
$user['sex'] = $member->sex;
|
||
} else {
|
||
error_log('Exception sex on user_id=' . $id);
|
||
continue;
|
||
}
|
||
$user['face_score'] = $member->face_score;
|
||
$user['photo'] = $member->photo;
|
||
$user['location_longitude'] = $member->location_longitude;
|
||
$user['location_latitude'] = $member->location_latitude;
|
||
$user['rank_id'] = $member->rank_id;
|
||
$user['type'] = $member->type;
|
||
$user['name'] = $member->name;
|
||
$user['is_approved'] = $member->is_approved;
|
||
$user['approve_date'] = $member->approve_date;
|
||
$user['is_photo_audited'] = $member->is_photo_audited;
|
||
$user['is_real_approved'] = $member->is_real_approved;
|
||
$user['is_educate_approved'] = $member->is_educate_approved;
|
||
$negative_score = $member->negative_score;
|
||
//好友请求不处理,加负面分
|
||
$friend_request = Request::where('user_id', $id)->orderBy('id', 'desc')->limit(15)->get();
|
||
if (!empty($friend_request)) {
|
||
$index = 0;
|
||
foreach ($friend_request as $request) {
|
||
if ($request->status == 1 || $request->status == -1) {
|
||
break;
|
||
} else {
|
||
$index += 1;
|
||
}
|
||
}
|
||
if ($index > 0 && $index < 5) {
|
||
$negative_score += 10;
|
||
}
|
||
if ($index > 5 && $index < 10) {
|
||
$negative_score += 20;
|
||
}
|
||
if ($index > 10) {
|
||
$negative_score += 50;
|
||
}
|
||
}
|
||
if ($negative_score > 200) {
|
||
$negative_score = 200;
|
||
}
|
||
$user['negative_score'] = $negative_score;
|
||
$user['info_complete_score'] = $member->info_complete_score;
|
||
$user['liveness'] = $member->liveness;
|
||
$user['last_visit'] = $member->last_visit;
|
||
$user['deleted_at'] = $member->deleted_at;
|
||
$user['hidden_profile'] = $member->hidden_profile;
|
||
$user['mobile'] = $member->mobile;
|
||
$user['id'] = $member->id;
|
||
$user['init_time'] = date('Y-m-d H:i:s');
|
||
$time = mt_rand(60*60*12,60*60*24);
|
||
Redis::setex('ai:user:' . $id,$time, json_encode($user));
|
||
self::$static_ai_users[$id] = $user;
|
||
$receive_user_list[] = $id; //接收人
|
||
if ($profile->previews->count()) {
|
||
$preview_ids = [];
|
||
foreach ($profile->previews as $item) {
|
||
if (!in_array($item->user_id, $preview_ids)) { //重复查看详情,跳过
|
||
$preview_ids[] = $item->user_id;
|
||
}
|
||
}
|
||
self::$static_preview[$id] = $preview_ids;
|
||
Redis::set('ai:preview:' . $id, json_encode($preview_ids)); //查看详情信息入redis
|
||
}
|
||
if ($profile->browses->count()) {
|
||
$browse_ids = [];
|
||
foreach ($profile->browses as $item) {
|
||
if (!in_array($item->other_user_id, $browse_ids)) {
|
||
$browse_ids[] = $item->other_user_id;
|
||
}
|
||
}
|
||
Redis::set('ai:browse:' . $id, json_encode($browse_ids));
|
||
self::$static_browse[$id] = $browse_ids;
|
||
}
|
||
$except_ids = []; //异常idList
|
||
if ($profile->blacklists->count()) { //黑名单加到异常列表
|
||
foreach ($profile->blacklists as $item) {
|
||
if ($item->deleted_at == null) {
|
||
$except_ids[] = $item->other_user_id;
|
||
}
|
||
}
|
||
}
|
||
if ($profile->friends->count()) { //好友加到异常列表
|
||
foreach ($profile->friends as $item) {
|
||
$except_ids[] = $item->user_id;
|
||
}
|
||
}
|
||
if ($profile->requests->count()) { //好友请求加异常列表
|
||
foreach ($profile->requests as $item) {
|
||
$except_ids[] = $item->user_linking_id;
|
||
}
|
||
}
|
||
if ($profile->dislikes->count() > 0) { //不喜欢加异常列表
|
||
foreach ($profile->dislikes as $item) {
|
||
$except_ids[] = $item->type_id;
|
||
}
|
||
}
|
||
if (!empty($except_ids)) { //异常列表保存
|
||
Redis::set('ai:except:' . $id, json_encode(array_values(array_unique($except_ids))));
|
||
self::$static_user_except[$id] = $except_ids;
|
||
}
|
||
if ($member->type == 'single') { //单身
|
||
if ($member->sex == 1) {
|
||
if (!in_array($id, self::WORKER_USER_ID_LIST)) { //不在工作人员列表且实名
|
||
if ($member->is_real_approved || ($member->is_approved)) {
|
||
if (!empty($member->face_score) && $member->face_score > 40.0) { //颜值低于40不推荐
|
||
$send_male_ids[] = $id;
|
||
}
|
||
}
|
||
}
|
||
if (!in_array($id, $receive_male_ids)) {
|
||
$receive_male_ids[] = $id;
|
||
}
|
||
} else if ($member->sex == 2) {
|
||
if (!in_array($id, self::WORKER_USER_ID_LIST)) { //不在工作人员列表且实名
|
||
if ($member->is_real_approved || ($member->is_approved)) {
|
||
if (!empty($member->face_score) && $member->face_score > 40.0) { //颜值低于40不推荐
|
||
$send_female_ids[] = $id;
|
||
}
|
||
}
|
||
}
|
||
if (!in_array($id, $receive_female_ids)) {
|
||
$receive_female_ids[] = $id;
|
||
}
|
||
}
|
||
} else { //marriage和loveing
|
||
if ($member->sex == 1) {
|
||
$worker_male_ids[] = $id;
|
||
if (!in_array($id, $receive_male_ids)) {
|
||
$receive_male_ids[] = $id;
|
||
}
|
||
} else if ($member->sex == 2) {
|
||
$worker_female_ids[] = $id;
|
||
if (!in_array($id, $receive_female_ids)) {
|
||
$receive_female_ids[] = $id;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
});
|
||
Redis::set('ai:send:female:ids', json_encode(array_unique($send_female_ids)));
|
||
Redis::set('ai:send:male:ids', json_encode(array_unique($send_male_ids)));
|
||
Redis::set('ai:recv:ids', json_encode(array_unique($receive_user_list)));
|
||
Redis::set('ai:recv:female:ids', json_encode(array_unique($receive_female_ids)));
|
||
Redis::set('ai:recv:male:ids', json_encode(array_unique($receive_male_ids)));
|
||
Redis::set('ai:recv:female_marriage:ids', json_encode(array_unique($worker_female_ids))); //工作人员
|
||
Redis::set('ai:recv:male_marriage:ids', json_encode(array_unique($worker_male_ids))); //工作人员
|
||
//Log::notice('[initUser] save user, on:' . (self::micro_time_float() - $start) . ',total_user:' . $total_user . ',current: ' . $current_user);
|
||
return true;
|
||
}
|
||
|
||
/**
|
||
* 用户推荐主处理程序
|
||
* @param $receive_user_list
|
||
* @param $send_user_list
|
||
* @return array|\Illuminate\Support\Collection|null
|
||
*/
|
||
public function initRecommendScore($receive_user_list, $send_user_list,$recode_number)
|
||
{
|
||
try {
|
||
$items = null;
|
||
// $send_female_ids = json_decode(Redis::get('ai:send:female:ids'), true)?:[];
|
||
// Log::info("send_female_ids_count: :".count($send_female_ids));
|
||
// $send_male_ids = json_decode(Redis::get('ai:send:male:ids'), true)?:[];
|
||
// Log::info("send_male_ids_count: :".count($send_male_ids));
|
||
$redis = Redis::connection('big_data');
|
||
$send_female_ids = json_decode($redis->get('ai:send:female:ids'), true)?:[];
|
||
Log::info("send_female_ids_count: :".count($send_female_ids));
|
||
$send_male_ids = json_decode($redis->get('ai:send:male:ids'), true)?:[];
|
||
Log::info("send_male_ids_count: :".count($send_male_ids));
|
||
|
||
$index = 0;
|
||
if ($send_user_list) {
|
||
$inside = 1;
|
||
} else {
|
||
$inside = 0;
|
||
}
|
||
foreach ($receive_user_list as $receive_id) {
|
||
$index++;
|
||
$receive_user = $this->getUser($receive_id,'receive_user');
|
||
if (empty($receive_user)) {
|
||
continue;
|
||
}
|
||
if (empty($receive_user->type)) {
|
||
continue;
|
||
}
|
||
if ($receive_user->type == 'single') { //单身
|
||
if (!$send_user_list) {
|
||
if ($receive_user->sex == 1) {
|
||
$send_user_list = $send_female_ids;
|
||
} else {
|
||
$send_user_list = $send_male_ids;
|
||
}
|
||
}
|
||
} else { //marriage和loveing都是介绍人
|
||
$send_user_list = array_merge($send_male_ids, $send_female_ids);
|
||
}
|
||
if(empty($send_user_list)){
|
||
$this->initUser();
|
||
}
|
||
$exceptList = Redis::get('ai:except:' . $receive_id); //读取该用户ID的异常列表
|
||
if (!empty($exceptList)) { //从推荐的用户列表中排除在异常更表中的ID
|
||
$exceptList = json_decode($exceptList, true);
|
||
if(!empty($exceptList)){
|
||
$send_user_list = array_diff($send_user_list, $exceptList);
|
||
}
|
||
}
|
||
//$start1 = self::micro_time_float();
|
||
$items = collect();
|
||
$is_recmd_num = 0;
|
||
$is_valid_num = 0;
|
||
foreach ($send_user_list as $send_user) {
|
||
$result = $this->calculateUserScore($receive_id, $send_user);
|
||
if ($result && isset($result['data'])) {
|
||
$recmd = $result['data'];
|
||
$recmd->match_time = date('Y-m-d H:i:s');
|
||
$recmd->send_user = $this->getUser($send_user,'sender_user');
|
||
$items->push($recmd);
|
||
$is_recmd_num++;
|
||
if ($recmd->score > 150) { //如返回的score > 150,有效人数加1
|
||
$is_valid_num++;
|
||
}
|
||
//}
|
||
} else {
|
||
continue;
|
||
}
|
||
}
|
||
//$items->receive_user = $receive_user;
|
||
//$recmd_status->push(['id' => $receive_id, 'is_recmd_num' => $is_recmd_num, 'is_valid_num' => $is_valid_num]); //推荐状态
|
||
$items = $items->sortByDesc(function ($item) { //按分数排序
|
||
return $item->is_recommend * 100 + $item->score;
|
||
})->take($recode_number);
|
||
if (empty($items->toArray())) {
|
||
continue;
|
||
} else {
|
||
$items = array_values($items->toArray());
|
||
if ($inside) {
|
||
//Redis::setex('ai:recmd:score:inside:' . $receive_id, 60 * 60 * 24, json_encode($items));
|
||
} else {
|
||
Redis::setex('ai:recmd:score:all:' . $receive_id, 60 * 60 * 24, json_encode($items));
|
||
}
|
||
}
|
||
}
|
||
return $items;
|
||
}catch (\Exception $e){
|
||
throw new \Exception($e);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 当用户不在ai:user中时,检查不在原因
|
||
* @param $userId
|
||
* @return array|bool
|
||
* @throws \Calchen\LaravelDingtalkRobot\Exceptions\Exception
|
||
*/
|
||
public function checkUser($userId,$user_type)
|
||
{
|
||
try {
|
||
$user = Profile::leftJoin('users', 'profile_courtships.user_id', '=', 'users.id')
|
||
->select(
|
||
'profile_courtships.birthday', 'profile_courtships.belief', 'profile_courtships.province',
|
||
'profile_courtships.city', 'profile_courtships.state', 'profile_courtships.weight',
|
||
'profile_courtships.stature', 'profile_courtships.resident_province', 'profile_courtships.resident_city',
|
||
'profile_courtships.degree', 'profile_courtships.max_age', 'profile_courtships.min_age',
|
||
'profile_courtships.min_height', 'profile_courtships.max_height', 'profile_courtships.city_claim',
|
||
'profile_courtships.city_list_claim', 'profile_courtships.hometown_claim', 'profile_courtships.approve_claim',
|
||
'profile_courtships.belief', 'users.sex','profile_courtships.province','profile_courtships.city',
|
||
'users.face_score', 'users.photo','users.location_longitude', 'users.location_latitude','users.rank_id',
|
||
'users.type', 'users.is_approved','users.approve_date', 'users.is_photo_audited','users.is_real_approved',
|
||
'users.is_educate_approved', 'users.negative_score','users.info_complete_score', 'users.hidden_profile',
|
||
'users.mobile','users.id','users.name','users.last_visit')
|
||
->where('user_id', $userId)->first();
|
||
if ($user) {
|
||
if($user_type == 'sender_user'){
|
||
if ($user->hidden_profile != 'NONE') {
|
||
return ['status' => 'fail', 'data' => [], 'error' => '用户设置为隐藏'];
|
||
}
|
||
}
|
||
if (empty($user->sex)) {
|
||
return ['status' => 'fail', 'data' => [], 'error' => '用户未设置性别'];
|
||
} elseif (empty($user->province)) {
|
||
return ['status' => 'fail', 'data' => [], 'error' => '用户未设置省份'];
|
||
//} elseif (empty($user->city)) {
|
||
// return ['status' => 'fail', 'data' => [], 'error' => '用户未设置城市'];
|
||
} elseif (empty($user->state)) {
|
||
return ['status' => 'fail', 'data' => [], 'error' => '用户未设置单身状态'];
|
||
}
|
||
$user['init_time'] = date('Y-m-d H:i:s');
|
||
$time = mt_rand(60*60*12,60*60*24);
|
||
Redis::setex('ai:user:' . $user->id,$time,json_encode($user));
|
||
self::$static_ai_users[$user->id] = $user;
|
||
return $user;
|
||
} else {
|
||
return ['status' => 'fail', 'data' => [], 'error' => '没有这个用户'];
|
||
}
|
||
} catch (Exception $e) {
|
||
return false;
|
||
}
|
||
|
||
}
|
||
|
||
/**
|
||
* 字符串截取指定长度
|
||
* @param $text
|
||
* @param $length
|
||
* @param string $replace
|
||
* @param string $encoding
|
||
* @return string
|
||
*/
|
||
public function substring_format($text, $length, $replace = '......', $encoding = 'UTF-8')
|
||
{
|
||
if ($text && mb_strlen($text, $encoding) > $length) {
|
||
return mb_substr($text, 0, $length, $encoding) . $replace;
|
||
}
|
||
return $text;
|
||
}
|
||
|
||
/**
|
||
* 计算两个用户的分值
|
||
* 将send_user_id 推给 user_id
|
||
* @param $user_id
|
||
* @param $send_user_id
|
||
* @param bool $is_full
|
||
* @return bool|mixed
|
||
* @throws \Calchen\LaravelDingtalkRobot\Exceptions\Exception
|
||
*/
|
||
public function calculateUserScore($user_id, $send_user_id)
|
||
{
|
||
//获取用户信息
|
||
$user = $this->getUser($user_id,'receive_user');
|
||
if (empty($user)) {
|
||
return ['code' => 1, 'msg' => "用户【" . $user_id . "】没有缓存数据,"];
|
||
}
|
||
$send_user = $this->getUser($send_user_id,'sender_user');
|
||
if (empty($send_user)) {
|
||
return ['code' => 1, 'msg' => "用户【" . $send_user_id . "】没有缓存数据,"];
|
||
}
|
||
/**
|
||
if (empty($send_user->photo)) {
|
||
return ['code' => 1, 'msg' => "用户【" . $send_user_id . "】没有头像,"];
|
||
}
|
||
**/
|
||
if ($user->type == 'single' && $user->type == $send_user->type && $user->sex == $send_user->sex) {
|
||
return ['code' => 1, 'msg' => ' send_user_id - user_id :' . $send_user_id . '-' . $user_id . ',单身同性别,'];
|
||
}
|
||
/**
|
||
//颜值低于40的用户不推荐
|
||
if ($send_user->face_score == 0.00 || $send_user->face_score < 30.00) {
|
||
return ['code' => 1, 'msg' => ' send_user_id ' . $send_user_id . ' 颜值低于40,不能推荐,'];
|
||
}
|
||
**/
|
||
/** 检测单身状态 */
|
||
/**
|
||
$type_res = $this->checkType($user, $send_user);
|
||
if (!empty($type_res['code'])) return $type_res;
|
||
**/
|
||
$msg = '';
|
||
|
||
// 计算基础分数
|
||
$base_res = $this->calculateBaseScore($user, $send_user);
|
||
if ($base_res['code']) return $base_res;
|
||
$base_score = $base_res['data'];
|
||
$msg .= $base_res['msg'];
|
||
|
||
/**
|
||
// 计算动态分
|
||
$dynamic_res = $this->calculateDynamicScore($user, $send_user);
|
||
if ($dynamic_res['code']) return $dynamic_res;
|
||
$dynamic_score = $dynamic_res['data'];
|
||
$msg .= $dynamic_res['msg'];
|
||
**/
|
||
|
||
// 计算负分
|
||
$negative_res = $this->calculateNegativeScore($user, $send_user);
|
||
if ($negative_res['code']) return $negative_res;
|
||
$negative_score = $negative_res['data'];
|
||
$msg .= $negative_res['msg'];
|
||
|
||
// 计算婚姻状况
|
||
$marital_status = $this->calculateMaritalStatus($user, $send_user);
|
||
if ($marital_status['code']) return $marital_status;
|
||
$marital_status_score = $marital_status['data'];
|
||
$msg .= $marital_status['msg'];
|
||
|
||
$result = json_decode('{"send_user":' . $send_user_id . ',"receive_user":' . $user_id . '}');
|
||
$result->is_recommend = ($base_score == 150) ? 1 : 0;
|
||
$result->base_score = $base_score;
|
||
$result->marital_status_score = $marital_status_score;
|
||
$result->base_score = $base_score;
|
||
$result->negtive_score = $negative_score;
|
||
//$result->dync_score = $dynamic_score;
|
||
$result->score = $base_score + $marital_status_score - $negative_score; //$dynamic_score;
|
||
return ['code' => 0, 'msg' => $msg, 'data' => $result];
|
||
}
|
||
|
||
/**
|
||
* 获取用户
|
||
* @param $id
|
||
* @return bool|mixed|object
|
||
* @throws \Calchen\LaravelDingtalkRobot\Exceptions\Exception
|
||
*/
|
||
public function getUser($id,$user_type)
|
||
{
|
||
try {
|
||
if (isset(self::$static_ai_users[$id])) {
|
||
$user = self::$static_ai_users[$id];
|
||
if($user){
|
||
if(!empty($user['init_time'])) {
|
||
if (time() - strtotime($user['init_time']) >= 86400) {
|
||
unset(self::$static_ai_users[$id]);
|
||
$user = null;
|
||
}
|
||
}else{
|
||
unset(self::$static_ai_users[$id]);
|
||
$user = null;
|
||
}
|
||
}
|
||
} else {
|
||
$user = json_decode(Redis::get('ai:user:' . $id), true);
|
||
}
|
||
if (empty($user->id)) {
|
||
$user = $this->checkUser($id,$user_type);
|
||
if(!empty($user['status'])){
|
||
return false;
|
||
}
|
||
Redis::setex('ai:user:' . $id,60*60*24,json_encode($user));
|
||
self::$static_ai_users[$id] = $user;
|
||
return $user;
|
||
}
|
||
if (is_array($user)) {
|
||
$user = (object)$user;
|
||
}
|
||
return $user;
|
||
} catch (Exception $e) {
|
||
return false;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 检测单身状态
|
||
* @param $user
|
||
* @param $send_user
|
||
* @return array
|
||
* @throws \Calchen\LaravelDingtalkRobot\Exceptions\Exception
|
||
*/
|
||
public function checkType($user, $send_user):array
|
||
{
|
||
try {
|
||
if (empty($user->type) || empty($user->sex) || empty($send_user->sex) || empty($send_user->type)) {
|
||
return ['code'=>1, 'msg'=>'user_id = ' . $user->id . ', send_user_id =' . $send_user->id . " 有性别信息或者没有用户类型,"];
|
||
}
|
||
//类型不同
|
||
if ($user->type != $send_user->type) {
|
||
//单身
|
||
if ($user->type == 'signle') {
|
||
return ['code'=>1, 'msg'=>'receive_user_id = ' . $user->id . ',send_user_id = ' . $send_user->id . " 介绍人不能匹配给单身,"];
|
||
}
|
||
} else {
|
||
if ($send_user->type != 'single') {
|
||
return ['code'=>1, 'msg'=>'receive_user_id = ' . $user->id . ',send_user_id = ' . $send_user->id . " 介绍人之间不能相互匹配,"];
|
||
}
|
||
}
|
||
return ['code'=>0, 'msg'=>''];
|
||
} catch (Exception $e) {
|
||
return ['code'=>1, 'msg'=>'计算receive_user_id=' . $user->id . ',sendUserId=' . $send_user->id . '计算检测单身状态出错,请及时处理!!!,'];
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 婚姻状况检测
|
||
* @param $user
|
||
* @param $send_user
|
||
* @return array
|
||
*/
|
||
public function calculateMaritalStatus($user, $send_user): array
|
||
{
|
||
try{
|
||
if($user->state && $send_user->state) {
|
||
if ($user->state == $send_user->state) {
|
||
$score = 10;
|
||
} elseif(($user->state == '从未结婚' && $send_user->state == '未婚') || ($send_user->state == '从未结婚' && $user->state == '未婚')) {
|
||
$score = 10;
|
||
}else{
|
||
$score = 0;
|
||
}
|
||
}else{
|
||
$score = 10;
|
||
}
|
||
return ['code'=>0, 'msg'=>'ok', 'data'=>$score];
|
||
} catch (Exception $e) {
|
||
return ['code'=>1, 'msg'=>'计算userId=' . $user->id . ',sendUserId=' . $send_user->id . '计算基础分数出错,请及时处理!!!,'];
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 计算基础分数
|
||
* @param $user
|
||
* @param $send_user
|
||
* @return array
|
||
* @throws \Calchen\LaravelDingtalkRobot\Exceptions\Exception
|
||
*/
|
||
public function calculateBaseScore($user, $send_user):array
|
||
{
|
||
try {
|
||
$score = 0;
|
||
$msg = '';
|
||
/** 计算信仰 */
|
||
$belief_res = $this->calculateBelief($user, $send_user);
|
||
if (!empty($belief_res['code'])) return $belief_res;
|
||
$score += $belief_res['data'];
|
||
$msg .= $belief_res['msg'];
|
||
|
||
/** 计算年龄 */
|
||
$age_res = $this->calculateAge($user, $send_user);
|
||
if (!empty($age_res['code'])) return $age_res;
|
||
$score += $age_res['data'];
|
||
$msg .= $age_res['msg'];
|
||
|
||
/** 计算地域 */
|
||
$regional_res = $this->calculateRegional($user, $send_user);
|
||
if ($regional_res['code']) return $regional_res;
|
||
$score += $regional_res['data'] * 1.1;
|
||
$msg .= $regional_res['msg'];
|
||
|
||
/** 计算学历 */
|
||
$degree_res = $this->calculateDegreeBaseScore($user, $send_user);
|
||
if ($degree_res['code']) return $degree_res;
|
||
$score += $degree_res['data'];
|
||
$msg .= $degree_res['msg'];
|
||
|
||
/** 计算身高 */
|
||
$stature_res = $this->calculateStature($user, $send_user);
|
||
if ($stature_res['code']) return $stature_res;
|
||
//$score += $stature_res['data'];
|
||
$msg .= $stature_res['msg'];
|
||
|
||
/** 计算单身状态 */
|
||
$state_res = $this->calculateState($user, $send_user);
|
||
if ($state_res['code']) return $state_res;
|
||
$score += $state_res['data'];
|
||
$msg .= $state_res['msg'];
|
||
|
||
return ['code'=>0, 'msg'=>$msg, 'data'=>$score];
|
||
} catch (Exception $e) {
|
||
return ['code'=>1, 'msg'=>'计算userId=' . $user->id . ',sendUserId=' . $send_user->id . '计算基础分数出错,请及时处理!!!,'];
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 计算信仰分数
|
||
* @param $user
|
||
* @param $send_user
|
||
* @throws \Calchen\LaravelDingtalkRobot\Exceptions\Exception
|
||
*/
|
||
public function calculateBelief($user, $send_user):array
|
||
{
|
||
try {
|
||
$score = 10;
|
||
//同信仰
|
||
if ($user->belief == $send_user->belief) {
|
||
return ['code'=>0, 'msg'=>'','data'=>$score];
|
||
}
|
||
//非同信仰
|
||
if (($user->belief == '基督教' && $send_user->belief != '基督教') || ($user->belief == '伊斯兰教' && $send_user->belief != '伊斯兰教') || ($send_user->belief == '基督教' && $user->belief != '基督教') || ($send_user->belief == '伊斯兰教' && $user->belief != '伊斯兰教')) {
|
||
return ['code'=>0, 'msg'=>'','data'=>0];
|
||
}
|
||
return ['code'=>0, 'msg'=>'','data'=>$score];
|
||
} catch (Exception $e) {
|
||
return ['code'=>1, 'msg'=> '计算userId=' . $user->id . ',sendUserId=' . $send_user->id . '计算信仰分数出错,请及时处理!!!,'];
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 计算年龄分数
|
||
* @param $user
|
||
* @param $send_user
|
||
* @return array
|
||
* @throws \Calchen\LaravelDingtalkRobot\Exceptions\Exception
|
||
*/
|
||
public function calculateAge($user, $send_user):array
|
||
{
|
||
try {
|
||
$score = 10;
|
||
$user_age = $this->getAge($user->birthday);
|
||
$send_user_age = $this->getAge($send_user->birthday);
|
||
$max_age = $this->getAge($user->max_age);
|
||
$min_age = $this->getAge($user->min_age);
|
||
$sub_age = $user_age - $send_user_age;
|
||
if ($user->type != 'single') {
|
||
if ($send_user_age>=22 and $send_user_age<=35) {
|
||
return ['code'=>0, 'msg'=>'', 'data'=>$score];
|
||
}else{
|
||
return ['code'=>0, 'msg'=>'介绍人推荐的年龄不在22-35之间,', 'data'=>0];
|
||
}
|
||
}
|
||
|
||
//是否要求
|
||
if ($min_age && $max_age) { //有要求
|
||
if ($send_user_age < $min_age || $send_user_age > $max_age) {
|
||
return ['code'=>0, 'msg'=>'推荐的年龄不在用户要求范围内'.$min_age.'-'.$max_age.'之间,', 'data'=>0];
|
||
}
|
||
} else {
|
||
if ($user->sex == 1) { //男
|
||
if ($user_age >= 45) {
|
||
if ($send_user_age < 40) {
|
||
return ['code'=>0, 'msg'=>'45岁以上男用户推荐的年龄小于40,', 'data'=>0];
|
||
}
|
||
} elseif ($user_age >= 35 && $user_age < 45) {
|
||
if ($sub_age < -5 || $sub_age > 7) {
|
||
return ['code'=>0, 'msg'=>'35-45岁男用户推荐的年龄不在小5岁大7岁之间,', 'data'=>0];
|
||
}
|
||
} else {
|
||
if ($sub_age < -3 || $sub_age > 5) {
|
||
return ['code'=>0, 'msg'=>'35岁以下男用户推荐的年龄不在小3岁大7岁之间,', 'data'=>0];
|
||
}
|
||
}
|
||
} else { //女
|
||
if ($user_age >= 40) {
|
||
if ($send_user_age < 40) {
|
||
return ['code'=>0, 'msg'=>'40岁以上女用户推荐的年龄小于40,', 'data'=>0];
|
||
}
|
||
} elseif ($user_age >= 30 && $user_age < 40) {
|
||
if ($sub_age < -7 || $sub_age > 5) {
|
||
return ['code'=>0, 'msg'=>'30-40岁女用户推荐的年龄不在小7岁大5岁之间,', 'data'=>0];
|
||
}
|
||
} else {
|
||
if ($sub_age < -7 || $sub_age > 3) {
|
||
return ['code'=>0, 'msg'=>'30岁以下女用户推荐的年龄不在小7岁大3岁之间,', 'data'=>0];
|
||
}
|
||
}
|
||
}
|
||
}
|
||
return ['code'=>0, 'msg'=>'', 'data'=>$score];
|
||
} catch (Exception $e) {
|
||
return ['code'=>1, 'msg'=>'计算userId=' . $user->id . ',sendUserId=' . $send_user->id . '年龄分数出错,请及时处理!!!,'];
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 获取年龄
|
||
* @param string $birthday 生日
|
||
* @return integer 年龄
|
||
*/
|
||
public function getAge($birthday): int
|
||
{
|
||
if (empty($birthday)) {
|
||
return 0;
|
||
}
|
||
$age = strtotime($birthday);
|
||
if ($age === false) {
|
||
return 0;
|
||
}
|
||
list($y1, $m1, $d1) = explode("-", date("Y-m-d", $age));
|
||
$now = strtotime("now");
|
||
list($y2, $m2, $d2) = explode("-", date("Y-m-d", $now));
|
||
$age = $y2 - $y1;
|
||
if ((int)($m2 . $d2) < (int)($m1 . $d1))
|
||
$age -= 1;
|
||
return $age;
|
||
}
|
||
|
||
/**
|
||
* 计算地域分数
|
||
* @param $user
|
||
* @param $send_user
|
||
* @return array
|
||
*/
|
||
public function calculateRegional($user, $send_user):array
|
||
{
|
||
try{
|
||
$score = 0;
|
||
if($user->province == $send_user->province){
|
||
$score += 5;
|
||
if($user->city == $send_user->city){
|
||
$score += 10;
|
||
}
|
||
if($user->resident_province == $send_user->resident_province){
|
||
$score += 5;
|
||
}
|
||
if($user->resident_city == $send_user->resident_city){
|
||
$score += 10;
|
||
}
|
||
}else{
|
||
if($user->resident_province == $send_user->resident_province){
|
||
$score += 5;
|
||
}
|
||
if($user->resident_city == $send_user->resident_city){
|
||
$score += 10;
|
||
}
|
||
}
|
||
return ['code'=>0, 'msg'=>'', 'data'=>$score];
|
||
}catch(\Exception $e){
|
||
return false;
|
||
}
|
||
}
|
||
|
||
/**
|
||
*计算某个经纬度的周围某段距离的正方形的四个点
|
||
* @param $lng
|
||
* @param $lat
|
||
* @param float $distance
|
||
* @return array 正方形的四个点的经纬度坐标
|
||
*/
|
||
static function returnSquarePoint($lng, $lat, $distance = 0.5)
|
||
{
|
||
$EARTH_RADIUS = 6371;//地球半径,平均半径为6371km
|
||
$dlng = 2 * asin(sin($distance / (2 * $EARTH_RADIUS)) / cos(deg2rad($lat)));
|
||
$dlng = rad2deg($dlng);
|
||
$dlat = $distance / $EARTH_RADIUS;
|
||
$dlat = rad2deg($dlat);
|
||
return array(
|
||
'left_top' => array('lat' => round($lat + $dlat, 2), 'lng' => round($lng - $dlng, 2)),
|
||
'right_top' => array('lat' => round($lat + $dlat, 2), 'lng' => round($lng + $dlng, 2)),
|
||
'left_bottom' => array('lat' => round($lat - $dlat, 2), 'lng' => round($lng - $dlng, 2)),
|
||
'right_bottom' => array('lat' => round($lat - $dlat, 2), 'lng' => round($lng + $dlng, 2))
|
||
);
|
||
}
|
||
|
||
/**
|
||
* 计算基础学历分数
|
||
* @param $user
|
||
* @param $send_user
|
||
* @return arary
|
||
*/
|
||
public function calculateDegreeBaseScore($user, $send_user):array
|
||
{
|
||
$score = 10;
|
||
if ($user->type != 'single') {
|
||
return ['code'=>0, 'msg'=>'', 'data'=>10];
|
||
}
|
||
if (empty($user->degree) || $user->degree == '其它') {
|
||
$score = 10;
|
||
} elseif (!empty($user->degree) && !empty($send_user->degree)) {
|
||
$user_degree_number = self::degree[$send_user->degree];
|
||
$send_user_degree_number = self::degree[$user->degree];
|
||
if ($user->degree >= 4) {
|
||
if ($send_user_degree_number > $user_degree_number) {
|
||
$sub_degree = $send_user_degree_number - $user_degree_number;
|
||
if($sub_degree > 2){
|
||
$score = 0;
|
||
}
|
||
} else {
|
||
$sub_degree = $user_degree_number - $send_user_degree_number;
|
||
if($sub_degree > 2){
|
||
$score = 0;
|
||
}
|
||
}
|
||
} else {
|
||
if ($send_user_degree_number > $user_degree_number) {
|
||
$sub_degree = $send_user_degree_number - $user_degree_number;
|
||
if($sub_degree > 2){
|
||
$score = 0;
|
||
}
|
||
}elseif ($send_user_degree_number < $user_degree_number) {
|
||
$sub_degree = $user_degree_number - $send_user_degree_number;
|
||
if($sub_degree > 2){
|
||
$score = 0;
|
||
}
|
||
}
|
||
}
|
||
} elseif (empty($user->degree) || !empty($send_user->degree)) {
|
||
$score = 10;
|
||
} else {
|
||
return ['code'=>0, 'msg'=>'学历不匹配,', 'data'=>0];
|
||
}
|
||
return ['code'=>0, 'msg'=>'', 'data'=>$score];
|
||
}
|
||
|
||
/**
|
||
* 计算身高分数
|
||
* @param $user
|
||
* @param $send_user
|
||
* @return array
|
||
* @throws \Calchen\LaravelDingtalkRobot\Exceptions\Exception
|
||
*/
|
||
public function calculateStature($user, $send_user):array
|
||
{
|
||
try {
|
||
$score = 10;
|
||
if (isset($user->max_height) && isset($send_user->max_height) && $user->max_height && $user->min_height) {
|
||
if ($send_user->stature < $user->min_height){
|
||
$sub_stature = $user->min_height - $send_user->stature;
|
||
$score = $score - $sub_stature;
|
||
if($score <= 5){
|
||
$score = 5;
|
||
}
|
||
}
|
||
}elseif($send_user->stature > $user->max_height) {
|
||
$sub_stature = $send_user->stature - $user->min_height;
|
||
$score = $score + $sub_stature;
|
||
if($score >= 12){
|
||
$score = 12;
|
||
}
|
||
}
|
||
return ['code'=>0, 'msg'=>'', 'data'=>$score];
|
||
} catch (Exception $e) {
|
||
return ['code'=>1, 'msg'=>'计算userId=' . $user->id . ',sendUserId=' . $send_user->id . '身高分数出错,请及时处理!!!,'];
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 计算单身状态分数
|
||
* @param $user
|
||
* @param $send_user
|
||
* @return array
|
||
* @throws \Calchen\LaravelDingtalkRobot\Exceptions\Exception
|
||
*/
|
||
public function calculateState($user, $send_user):array
|
||
{
|
||
try {
|
||
$score = 10;
|
||
return ['code'=>0, 'msg'=>'', 'data'=>$score];
|
||
} catch (Exception $e) {
|
||
return ['code'=>1, 'msg'=>'计算userId=' . $user->id . ',sendUserId=' . $send_user->id . '单身状态分数出错,请及时处理!!!,'];
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 计算动态分值
|
||
* @param $user
|
||
* @param $send_user
|
||
* @return array
|
||
* @throws \Calchen\LaravelDingtalkRobot\Exceptions\Exception
|
||
*/
|
||
public function calculateDynamicScore($user, $send_user):array
|
||
{
|
||
try {
|
||
$score = 0;
|
||
|
||
//认证分数
|
||
$approve_res= $this->calculateApprove($send_user);
|
||
if ($approve_res['code']) return $approve_res;
|
||
$score += (int)$approve_res['data'];
|
||
|
||
//地域分数
|
||
$regional_res = $this->calculateDynamicRegional($user, $send_user);
|
||
if ($regional_res['code']) return $regional_res;
|
||
$score += (int)$regional_res['data'];
|
||
|
||
//活跃度
|
||
$liveness_res = $this->calculateLikeness($user, $send_user);
|
||
if ($liveness_res['code']) return $liveness_res;
|
||
$score += (int)$liveness_res['data'];
|
||
|
||
//个人介绍完整度分数
|
||
$intro_res = $this->calculateIntroScore($send_user);
|
||
if ($intro_res['code']) return $intro_res;
|
||
$score += (int)$intro_res['data'];
|
||
|
||
|
||
//信息完整度
|
||
$complete_info_res = $this->calculateCompleteInfo($send_user);
|
||
if ($complete_info_res['code']) return $complete_info_res;
|
||
$score += (int)$complete_info_res['data'];
|
||
|
||
//生活照分数
|
||
$live_photo_res = $this->calculateLivePhoto($send_user);
|
||
if ($live_photo_res['code']) return $live_photo_res;
|
||
$score += (int)$live_photo_res['data'];
|
||
|
||
//颜值分数
|
||
$face_res = $this->calculateFaceScore($user,$send_user);
|
||
if ($face_res['code']) return $face_res;
|
||
$score += (int)$face_res['data'];
|
||
|
||
//学历分数
|
||
$degree_res = $this->calculateDegreeDynamicScore($user, $send_user);
|
||
if ($degree_res['code']) return $degree_res;
|
||
$score += (int)$degree_res['data'];
|
||
|
||
return ['code'=>0, 'msg'=>'', 'data'=>$score];
|
||
} catch (Exception $e) {
|
||
return ['code'=>1, 'msg'=> '计算userId=' . $user->id . ',sendUserId=' . $send_user->id . '动态分值出错,请及时处理!!!,'];
|
||
}
|
||
|
||
}
|
||
|
||
/**
|
||
* 计算认证分数
|
||
* @param $send_user
|
||
* @return array
|
||
* @throws \Calchen\LaravelDingtalkRobot\Exceptions\Exception
|
||
*/
|
||
public function calculateApprove($send_user):array
|
||
{
|
||
try {
|
||
$score = 0;
|
||
if ($send_user->is_approved) {
|
||
$score += 1;
|
||
}
|
||
if ($send_user->is_real_approved) {
|
||
$score += 2;
|
||
}
|
||
if ($send_user->face_score >= 80) {
|
||
$score += 2;
|
||
}
|
||
if ($send_user->is_educate_approved) {
|
||
$score += 2;
|
||
}
|
||
if ($send_user->rank_id > 0) {
|
||
$score += 2;
|
||
}
|
||
//申请推荐
|
||
return ['code'=>0, 'msg'=>'', 'data'=>$score];
|
||
} catch (Exception $e) {
|
||
return ['code'=>0, 'msg'=>'计算userId=' . $send_user->id . ',认证分数出错,请及时处理!!!,'];
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 计算动态地域分值
|
||
* @param $user
|
||
* @param $send_user
|
||
* @return array
|
||
* @throws \Calchen\LaravelDingtalkRobot\Exceptions\Exception
|
||
*/
|
||
public function calculateDynamicRegional($user, $send_user):array
|
||
{
|
||
try {
|
||
$score = 0;
|
||
if (($user->province != $send_user->province || empty($send_user->province)) && ($user->resident_province != $send_user->resident_province || empty($send_user->resident_province))) {
|
||
//非同省同家乡 或者 没有地址信息
|
||
$score = 0;
|
||
} elseif (($user->province != $send_user->province || empty($send_user->province)) && ($user->resident_province == $send_user->resident_province && $user->resident_city != $send_user->resident_city)) {
|
||
//非同省、同家乡省、非同家乡市
|
||
$score += $user->type=="single"?5:5;
|
||
} elseif (($user->province != $send_user->province || empty($send_user->province)) && $user->resident_city == $send_user->resident_city) {
|
||
//非同省、同家乡省市
|
||
$score += $user->type=="single"?12:12;
|
||
} elseif (($user->province == $send_user->province && $user->city != $send_user->city) && ($user->resident_province != $send_user->resident_province || empty($send_user->resident_province))) {
|
||
//同省非同市、非同家乡省
|
||
$score += $user->type=="single"?5:5;
|
||
} elseif (($user->province == $send_user->province && $user->city != $send_user->city) && ($user->resident_province == $send_user->resident_province && $user->resident_city != $send_user->resident_city)) {
|
||
//同省非同市、同家乡省非同家乡市
|
||
$score += $user->type=="single"?10:10;
|
||
} elseif (($user->province == $send_user->province && $user->city != $send_user->city) && $user->resident_city == $send_user->resident_city) {
|
||
//同省非同市、同家乡市
|
||
$score += $user->type=="single"?17:17;
|
||
} elseif ($user->city != $send_user->city && $user->resident_province != $send_user->resident_province) {
|
||
//同市、同家乡省
|
||
$score += $user->type=="single"?0:0;
|
||
} elseif (($user->province == $send_user->province && $user->city != $send_user->city) && $user->resident_city == $send_user->resident_city) {
|
||
//同省非同市、同家乡市
|
||
$score += $user->type=="single"?17:17;
|
||
} elseif ($user->city == $send_user->city && $user->resident_city == $send_user->resident_city) {
|
||
//同省非同市、同家乡市
|
||
$score += $user->type=="single"?24:24;
|
||
}
|
||
return ['code'=>0, 'msg'=>'', 'data'=>$score];
|
||
} catch (Exception $e) {
|
||
return ['code'=>1, 'msg'=>'计算userId=' . $user->id . ',sendUserId=' . $send_user->id . '动态地域分值出错,请及时处理!!!,'];
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 计算活跃度分数
|
||
* @param $user
|
||
* @param $send_user
|
||
* @return array
|
||
* @throws \Calchen\LaravelDingtalkRobot\Exceptions\Exception
|
||
*/
|
||
public function calculateLikeness($user, $send_user):array
|
||
{
|
||
try {
|
||
$score = 0;
|
||
//24小时内
|
||
$day_visit = strtotime($send_user->last_visit) + 24 * 3600 > time() ? 1 : 0;
|
||
//本周活跃
|
||
$week_visit = strtotime($send_user->last_visit) + 7 * 24 * 3600 > time() ? 1 : 0;
|
||
//本月活跃
|
||
$month_visit = strtotime($send_user->last_visit) + 30 * 24 * 3600 > time() ? 1 : 0;
|
||
//本年
|
||
$year_visit = strtotime($send_user->last_visit) + 365 * 24 * 3600 > time() ? 1 : 0;
|
||
if ($day_visit) {
|
||
$score = 10;
|
||
} elseif ($week_visit) {
|
||
$score = 5;
|
||
} elseif ($month_visit) {
|
||
$score = 2;
|
||
} elseif ($year_visit) {
|
||
$score = 1;
|
||
}
|
||
return ['code'=>0, 'msg'=>'', 'data'=>$score];
|
||
} catch (Exception $e) {
|
||
return ['code'=>1, 'msg'=>'计算userId=' . $user->id . ',sendUserId=' . $send_user->id . '活跃度分数出错,请及时处理!!!,'];
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 计算个人介绍分数
|
||
* @param $send_user
|
||
* @return array
|
||
* @throws \Calchen\LaravelDingtalkRobot\Exceptions\Exception
|
||
*/
|
||
public function calculateIntroScore($send_user):array
|
||
{
|
||
try {
|
||
$score = isset($send_user->show_score) ? 10: 0;
|
||
return ['code'=>0, 'msg'=>'', 'data'=>$score];
|
||
} catch (Exception $e) {
|
||
return ['code'=>1, 'msg'=>'计算个人介绍分数出错,请及时处理!!!,'];
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 计算新用户分数
|
||
* @param $send_user
|
||
* @return array
|
||
* @throws \Calchen\LaravelDingtalkRobot\Exceptions\Exception
|
||
*/
|
||
public function calculateNewApprove($send_user)
|
||
{
|
||
try {
|
||
$score = 0;
|
||
$current_time = time();
|
||
$approve_time = strtotime($send_user->approve_date);
|
||
if ($approve_time + 3 * 24 * 3600 >= $current_time) {
|
||
$score = 10;
|
||
}
|
||
return ['code'=>0, 'msg'=>'', 'data'=>$score];
|
||
} catch (Exception $e) {
|
||
return ['code'=>0, 'msg'=> '计算userId=' . $send_user->id . ',新用户分数出错,请及时处理!!!,'];
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 计算信息完整度分数
|
||
* @param $send_user
|
||
* @return array
|
||
* @throws \Calchen\LaravelDingtalkRobot\Exceptions\Exception
|
||
*/
|
||
public function calculateCompleteInfo($send_user)
|
||
{
|
||
try {
|
||
$info_score = $send_user->info_complete_score;
|
||
$score = $info_score / 2;
|
||
return ['code'=>0, 'msg'=>'', 'data'=>$score];
|
||
} catch (Exception $e) {
|
||
return ['code'=>0, 'msg'=>'计算userId=' . $send_user->id . ',信息完整度分数出错,请及时处理!!!,'];
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 计算生活照分数
|
||
* @param $send_user
|
||
* @return array
|
||
* @throws \Calchen\LaravelDingtalkRobot\Exceptions\Exception
|
||
*/
|
||
public function calculateLivePhoto($send_user)
|
||
{
|
||
try {
|
||
$photos_count = isset($send_user->photos_count) ?: 0;
|
||
switch ($photos_count) {
|
||
case 0:
|
||
$score = 0;
|
||
break;
|
||
case 1:
|
||
$score = 4;
|
||
break;
|
||
case 2:
|
||
$score = 6;
|
||
break;
|
||
case 3:
|
||
$score = 8;
|
||
break;
|
||
default:
|
||
$score = 10;
|
||
break;
|
||
}
|
||
return ['code'=>0, 'msg'=>'','data'=>$score];
|
||
} catch (Exception $e) {
|
||
return ['code'=>1, 'msg'=>"计算userId=' . $send_user->id . ',生活照分数出错,请及时处理!!!,"];
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 计算颜值分数
|
||
* @param $send_user
|
||
* @return array
|
||
*/
|
||
public function calculateFaceScore($user,$send_user)
|
||
{
|
||
$score = 10;
|
||
if($user->face_score && $send_user->face_score){
|
||
if($send_user->face_score > $user->face_score ){
|
||
$sub_face = $send_user->face_score - $user->face_score;
|
||
if($sub_face > 10){
|
||
$score = 0;
|
||
}else {
|
||
$score = $score + $sub_face;
|
||
if($score > 12){
|
||
$score = 12;
|
||
}
|
||
}
|
||
|
||
}elseif($send_user->face_score < $user->face_score){
|
||
$sub_face = $user->face_score - $send_user->face_score;
|
||
if($sub_face >= 10){
|
||
$score = 0;
|
||
}else {
|
||
$score = $score - $sub_face;
|
||
if($score < 5){
|
||
$score = 5;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
return ['code'=>0, 'msg'=>'', 'data'=>$score];
|
||
}
|
||
|
||
/**
|
||
* 计算动态学历分数
|
||
* @param $user
|
||
* @param $send_user
|
||
* @return array
|
||
*/
|
||
public function calculateDegreeDynamicScore($user, $send_user)
|
||
{
|
||
|
||
if (empty($user->degree) || empty($send_user->degree)) {
|
||
$score = 10;
|
||
} elseif (!empty($user->degree) && !empty($send_user->degree)) {
|
||
$user_degree_number = self::degree[$user->degree];
|
||
$send_user_degree_number = self::degree[$user->degree];
|
||
if ($user_degree_number >= 4) {
|
||
if ($user_degree_number == $send_user_degree_number) {
|
||
$score = 10;
|
||
} elseif ($send_user_degree_number - $user_degree_number > 1) {
|
||
$score = 5;
|
||
} elseif ($user_degree_number - $send_user_degree_number > 1 && $send_user_degree_number > 4) {
|
||
$score = 3;
|
||
} else {
|
||
$score = 0;
|
||
}
|
||
|
||
} elseif ($user_degree_number < 4) {
|
||
if ($user_degree_number == $send_user_degree_number) {
|
||
$score = 10;
|
||
} elseif ($send_user_degree_number - $user_degree_number > 1) {
|
||
$score = 5;
|
||
} elseif ($user_degree_number - $send_user_degree_number = 1) {
|
||
$score = 3;
|
||
} else {
|
||
$score = 0;
|
||
}
|
||
} else {
|
||
$score = 0;
|
||
}
|
||
} elseif (empty($user->degree) || !empty($send_user->degree)) {
|
||
$score = 10;
|
||
} else {
|
||
$score = 0;
|
||
}
|
||
return ['code'=>0, 'msg'=>'', 'data'=>$score];
|
||
}
|
||
|
||
/**
|
||
* 计算负分和最近访问
|
||
* @param $user
|
||
* @param $send_user
|
||
* @return array
|
||
* @throws \Calchen\LaravelDingtalkRobot\Exceptions\Exception
|
||
*/
|
||
public function calculateNegativeScore($user, $send_user)
|
||
{
|
||
try {
|
||
//计算负面分
|
||
$negative_res = $this->calculateNegative($send_user);
|
||
if ($negative_res['code']) return $negative_res;
|
||
$negative_score = $negative_res['data'];
|
||
|
||
$visit_res = $this->calculateVisit($user, $send_user);
|
||
//计算访问扣除分数
|
||
if ($visit_res['code']) return $visit_res;
|
||
$visit_score = $visit_res['data'];
|
||
|
||
$score = $negative_score + $visit_score;
|
||
return ['code'=>0, 'msg'=>'', 'data'=>$score];
|
||
} catch (Exception $e) {
|
||
return ['code'=>1, 'msg'=>'计算userId=' . $user->id . ',sendUserId=' . $send_user->id . '计算负分和最近访问出错,请及时处理!!!,'];
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 计算负分
|
||
* @param $send_user
|
||
* @return array
|
||
* @throws \Calchen\LaravelDingtalkRobot\Exceptions\Exception
|
||
*/
|
||
public function calculateNegative($send_user)
|
||
{
|
||
try {
|
||
$score = $send_user->negative_score;
|
||
return ['code'=>0, 'msg'=>'', 'data'=>$score];
|
||
} catch (Exception $e) {
|
||
return ['code'=>1, 'msg'=>'计算userId=' . $send_user->id . ',负分出错,请及时处理!!!,'];
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 计算访问扣除分数
|
||
* @param $user
|
||
* @param $send_user
|
||
* @return array
|
||
* @throws \Calchen\LaravelDingtalkRobot\Exceptions\Exception
|
||
*/
|
||
public function calculateVisit($user, $send_user)
|
||
{
|
||
try {
|
||
//最近访问
|
||
$score = 0;
|
||
|
||
/*$preview_key = 'ai:preview:'.$user->id;
|
||
$log = Redis::get($preview_key);
|
||
if ($log){
|
||
$log_arr = json_decode($log, true);
|
||
$result = in_array($send_user->id, $log_arr);
|
||
if ($result) return $score = -50;
|
||
}
|
||
*/
|
||
$log = $this->getReview($user->id);
|
||
if ($log) {
|
||
if (in_array($send_user->id, $log)) {
|
||
$score -= 5;
|
||
}
|
||
}
|
||
//列表刷新
|
||
$browse = $this->getBrowse($user->id);
|
||
if ($browse) {
|
||
if (in_array($send_user->id, $browse)) {
|
||
$score -= 3;
|
||
}
|
||
}
|
||
return ['code'=>0, 'msg'=>'', 'data'=>$score];
|
||
} catch (Exception $e) {
|
||
return ['code'=>1, 'msg'=>'计算userId=' . $user->id . ',sendUserId=' . $send_user->id . '访问扣除分数出错,请及时处理!!!,'];
|
||
}
|
||
}
|
||
|
||
public function getReview($id)
|
||
{
|
||
if (isset(self::$static_ai_reviews[$id])) {
|
||
return self::$static_ai_reviews[$id];
|
||
} else {
|
||
return false;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 获取浏览记录缓存
|
||
* @param $id
|
||
* @return false|mixed
|
||
*/
|
||
public function getBrowse($id)
|
||
{
|
||
if (isset(self::$static_ai_browses[$id])) {
|
||
return self::$static_ai_browses[$id];
|
||
} else {
|
||
return false;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 计算两个坐标的距离
|
||
* @param $lng1 , $lng2 经度
|
||
* @param $lat1 , $lat2 纬度
|
||
* @param int $unit 单位 1:米 2:千米
|
||
* @param int $decimal 精度 保留小数位数
|
||
*/
|
||
function getDistance($lng1, $lat1, $lng2, $lat2, $unit = 1, $decimal = 2)
|
||
{
|
||
$earthdata = 6371;//地球半径,平均半径为6371km
|
||
// 将角度转为狐度
|
||
$radLat1 = deg2rad($lat1); //deg2rad()函数将角度转换为弧度
|
||
$radLat2 = deg2rad($lat2);
|
||
$radLng1 = deg2rad($lng1);
|
||
$radLng2 = deg2rad($lng2);
|
||
$dlat = $radLat1 - $radLat2;
|
||
$dlng = $radLng1 - $radLng2;
|
||
$length = 2 * asin(sqrt(pow(sin($dlat / 2), 2) + cos($radLat1) * cos($radLat2) * pow(sin($dlng / 2), 2))) * $earthdata * 1000;
|
||
|
||
if ($unit == 2) {
|
||
$length /= 1000;
|
||
}
|
||
$length = round($length, $decimal);
|
||
return $length;
|
||
}
|
||
|
||
/**
|
||
* 修改缓存分数
|
||
* @param $user
|
||
* @param $send_user
|
||
* @param $base_score
|
||
* @param $dynamic_score
|
||
* @param $negative_score
|
||
* @return bool
|
||
* @throws \Calchen\LaravelDingtalkRobot\Exceptions\Exception
|
||
*/
|
||
public function updateCacheScore($user, $send_user, $base_score, $dynamic_score, $negative_score)
|
||
{
|
||
try {
|
||
$recommend_user_key = 'ai:recmd:scores:' . $user->id;
|
||
$is_recommend = $base_score == 150 ? 1 : 0;
|
||
$score = $base_score + $dynamic_score - $negative_score;
|
||
$log = ['send_user' => $send_user->id, 'is_recommend' => $is_recommend, 'score' => $score, 'base_score' => $base_score, 'dync_score' => $dynamic_score, 'negative_score' => $negative_score];
|
||
$json_recommend = json_encode($log);
|
||
$recommend_log = Redis::set($recommend_user_key, $json_recommend);
|
||
return true;
|
||
} catch (Exception $e) {
|
||
return false;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 年龄转成时间
|
||
* @param $age
|
||
* @param string $symbol
|
||
* @return string
|
||
*/
|
||
public function ageToBirthday($age, $symbol = '-')
|
||
{
|
||
$age = $age == 0 ? 25 : $age;
|
||
$nowyear = date("Y", time());
|
||
$year = $nowyear - $age;
|
||
$monthArr = [];
|
||
for ($i = 1; $i < 13; $i++) {
|
||
$monthArr[] = $i < 10 ? '0' . $i : $i;
|
||
}
|
||
$dayArr = [];
|
||
for ($i = 1; $i < 29; $i++) {
|
||
$dayArr[] = $i < 10 ? '0' . $i : $i;
|
||
}
|
||
$month_key = array_rand($monthArr, 1);
|
||
$month = $monthArr[$month_key];
|
||
$date_tmp_stamp = strtotime($year . '-' . $month);
|
||
$day = '';
|
||
if ($month == '02' && date("t", $date_tmp_stamp) == '29') {
|
||
$dayArr = array_merge($dayArr, ['29']);
|
||
$day_key = array_rand($dayArr, 1);
|
||
$day = $dayArr[$day_key];
|
||
} else if ($month == '02' && date("t", $date_tmp_stamp) == '28') {
|
||
$day_key = array_rand($dayArr, 1);
|
||
$day = $dayArr[$day_key];
|
||
} else if (in_array($month, ['01', '03', '05', '07', '08', '10', '12'])) {
|
||
$dayArr = array_merge($dayArr, ['29', '30', '31']);
|
||
$day_key = array_rand($dayArr, 1);
|
||
$day = $dayArr[$day_key];
|
||
} else {
|
||
$dayArr = array_merge($dayArr, ['29', '30']);
|
||
$day_key = array_rand($dayArr, 1);
|
||
$day = $dayArr[$day_key];
|
||
}
|
||
return $year . $symbol . $month . $symbol . $day;
|
||
}
|
||
|
||
}
|