0, '小学' => 1, '初中' => 2, '初中及初中以下' => 2, '中专' => 4, '高中' => 4, '高中/中专' => 4, '大专' => 5, '专科' => 5, '本科' => 6, '硕士' => 7, '硕士以上' => 7,'博士' => 8, ]; function __construct() { // Log::notice('[CommonService] init global common services'); } /** * 字符串截取指定长度 * @param $text * @param $length * @param string $replace * @param string $encoding * @return string */ static 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, $send_user) { //$match['userId'] = $user->user_id; //$match['sendUserId'] = $send_user->user_id; /** 计算年龄 */ $match['age'] = $this->calculateAge($user, $send_user); /** 计算身高 */ $match['stature'] = $this->calculateStature($user, $send_user); /** 计算信仰 */ $match['belief'] = $this->calculateBelief($user, $send_user); /** 计算最低月收入 */ $match['salary'] = $this->calculateSalary($user, $send_user); /** 计算学历 */ $match['degree'] = $this->calculateDegreeScore($user, $send_user); /** 计算地域 */ $match['regional'] = $this->calculateRegional($user, $send_user); $match['total_score'] = $match['age']['分值'] + $match['stature']['分值'] + $match['belief']['分值'] + $match['degree']['分值'] + $match['regional']['分值']; return $match; } /** * 计算年龄分数 * @param $user * @param $send_user * @return array * @throws \Calchen\LaravelDingtalkRobot\Exceptions\Exception */ public function calculateAge($user, $send_user): array { $score = 10; $send_user_age = $this->getAge($send_user->birthday); if ($send_user_age < 18) { return ['code' => 1, '期望年龄' => '', '实际年龄' => $send_user_age, '分值' => 0]; } $mate_conditon = json_decode($user->mate_conditon, true); if ($mate_conditon && $mate_conditon['age'] != '年龄不限') { list($min_age, $max_age) = explode("-", $mate_conditon['age']); $max_age = str_replace('岁', "", $max_age); //是否要求 if ($min_age && $max_age) { //有要求 if ($send_user_age < $min_age) { $subAge = $min_age - $send_user_age; $score = $score + $subAge; if ($score > 10) { $score = 10; } return ['code' => 0, '期望年龄' => $min_age . '-' . $max_age . '之间,', '实际年龄' => $send_user_age, '分值' => $score]; } elseif ($send_user_age > $max_age) { $subAge = $send_user_age - $max_age; $score = $score - $subAge; if ($score < 0) { $score = 0; } return ['code' => 0, '期望年龄' => $min_age . '-' . $max_age . '之间,', '实际年龄' => $send_user_age, '分值' => $score]; } elseif ($send_user_age > $min_age && $send_user_age < $max_age) { return ['code' => 0, '期望年龄' => $min_age . '-' . $max_age . '之间,', '实际年龄' => $send_user_age, '分值' => $score]; } else { return ['code' => 0, '期望年龄' => $min_age . '-' . $max_age . '之间,', '实际年龄' => $send_user_age, '分值' => $score]; } } else { return ['code' => 0, '期望年龄' => $mate_conditon['age'], '实际年龄' => $send_user_age, '分值' => $score]; } } else { return ['code' => 0, '期望年龄' => '无要求', '实际年龄' => $send_user_age, '分值' => $score]; } } /** * 获取年龄 * @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 * @throws \Calchen\LaravelDingtalkRobot\Exceptions\Exception */ public function calculateStature($user, $send_user): array { $score = 10; $mate_conditon = json_decode($user->mate_conditon, true); if ($mate_conditon && $mate_conditon['stature'] != '身高不限') { list($min_height, $max_height) = explode("-", $mate_conditon['stature']); $max_height = str_replace('cm', "", $max_height); if(empty($max_height)){ $max_height = 190; } if (isset($min_height) || isset($max_height)) { if ($send_user->stature < $min_height) { $subStature = $min_height - $send_user->stature; $score = $score - $subStature; if ($score < 0) { $score = 0; } return ['code' => 0, '期望身高' => $min_height . '-' . $max_height . '之间,', '实际身高' => $send_user->stature, '分值' => $score]; } elseif ($send_user->stature > $max_height) { $subStature = $send_user->stature - $max_height; $score = $score + $subStature; if ($score > 10) { $score = 10; } return ['code' => 0, '期望身高' => $min_height . '-' . $max_height . '之间,', '实际身高' => $send_user->stature, '分值' => $score]; } elseif ($send_user->stature > $min_height && $send_user->stature < $max_height) { return ['code' => 0, '期望身高' => $min_height . '-' . $max_height . '之间,', '实际身高' => $send_user->stature, '分值' => $score]; } else { return ['code' => 0, '期望身高' => $min_height . '-' . $max_height . '之间,', '实际身高' => $send_user->stature, '分值' => $score]; } } else { return ['code' => 0, '期望身高' => '无要求,', '实际身高' => $send_user->stature, '分值' => $score]; } } else { if ($send_user->stature) { return ['code' => 0, '期望身高' => '无要求,', '实际身高' => $send_user->stature, '分值' => $score]; } else { return ['code' => 0, '期望身高' => '无要求,', '实际身高' => "未填写", '分值' => $score]; } } } /** * 计算信仰分数 * @param $user * @param $send_user * @throws \Calchen\LaravelDingtalkRobot\Exceptions\Exception */ public function calculateBelief($user, $send_user): array { $score = 10; if ($user->mate_conditon) { $mate_conditon = json_decode($user->mate_conditon, true); //有要求信仰 if ($mate_conditon && $mate_conditon['belief'] != '信仰不限') { //同信仰 if ($mate_conditon['belief'] == $send_user->belief) { return ['code' => 0, '要求信仰' => $mate_conditon['belief'], '用户信仰' => $send_user->belief, '分值' => $score]; } else { return ['code' => 0, '要求信仰' => $mate_conditon['belief'], '用户信仰' => $send_user->belief, '分值' => 0]; } } else { return ['code' => 0, '要求信仰' => '未要求', '用户信仰' => $send_user->belief, '分值' => $score]; } } else { return ['code' => 0, '要求信仰' => '未要求', '用户信仰' => $send_user->belief, '分值' => $score]; } } /** * 计算月收入 * @param $user * @param $send_user */ public function calculateSalary($user, $send_user): array { $mate_conditon = json_decode($user->mate_conditon, true); $score = 10; if (isset($mate_conditon['income']) && $mate_conditon['income'] != '月收入不限') { if (strpos($mate_conditon['income'], '-')) { list($min_salary, $max_salary) = explode("-", $mate_conditon['income']); if (strpos($min_salary, '千')) { $min_salary = str_replace('千', "", $min_salary); $min_salary = $min_salary * 12; } if (strpos($max_salary, '千')) { $max_salary = str_replace('千', "", $max_salary); $max_salary = $max_salary * 12; } if (strpos($min_salary, '万')) { $min_salary = str_replace('万', "", $min_salary); $min_salary = $min_salary * 10 * 12; } if (strpos($max_salary, '万')) { $max_salary = str_replace('万', "", $max_salary); $max_salary = $max_salary * 10 * 12; } } elseif (strpos($mate_conditon['income'], '以上')) { $min_salary = str_replace('万以上', "", $mate_conditon['income']); $min_salary = $min_salary * 10 * 12; $max_salary = $min_salary; } if ($send_user->income) { if (strpos($send_user->income, '~')) { list($send_user_min_salary, $send_user_max_salary) = explode('~', $send_user->income); $send_user_max_salary = str_replace("w", "", $send_user_max_salary); $send_user_salary = ($send_user_min_salary + $send_user_max_salary) / 2 * 10; if ($min_salary > $send_user_salary) { $sub_salary = $min_salary - $send_user_salary; $score = $score - $sub_salary; if ($score < 0) { $score = 0; } return ['code' => 0, '期望年薪' => $min_salary . '-' . $max_salary . '千', '实际年薪平均数' => $send_user_salary . '千', '分值' => $score]; } elseif ($max_salary < $send_user_salary) { return ['code' => 0, '期望年薪' => $min_salary . '-' . $max_salary . '千', '实际年薪平均数' => $send_user_salary . '千', '分值' => $score]; } elseif ($min_salary < $send_user_salary && $max_salary > $send_user_salary) { return ['code' => 0, '期望年薪' => $min_salary . '-' . $max_salary . '千', '实际年薪平均数' => $send_user_salary . '千', '分值' => $score]; } } elseif (strpos($send_user->income, '以下')) { $send_user_max_salary = str_replace("w以下", "", $send_user->income); $send_user_max_salary = $send_user_max_salary * 10; if ($min_salary > $send_user_max_salary) { $sub_salary = $min_salary - $send_user_max_salary; $score = $score - $sub_salary; if ($score < 0) { $score = 0; } return ['code' => 0, '期望年薪' => $min_salary . '-' . $max_salary . '千', '实际年薪' => $send_user_max_salary . '千以下', '分值' => $score]; } elseif ($send_user_max_salary > $max_salary) { return ['code' => 0, '期望年薪' => $min_salary . '-' . $max_salary . '千', '实际年薪' => $send_user_max_salary . '千以下', '分值' => $score]; } else { return ['code' => 0, '期望年薪' => $min_salary . '-' . $max_salary . '千', '实际年薪' => $send_user_max_salary . '千以下', '分值' => $score]; } } elseif (strpos($send_user->income, '以上')) { $send_user_min_salary = str_replace("w以上", "", $send_user->income); $send_user_min_salary = $send_user_min_salary * 10; if ($min_salary > $send_user_min_salary) { $sub_salary = $min_salary - $send_user_min_salary; $score = $score - $sub_salary; if ($score < 0) { $score = 0; } return ['code' => 0, '期望年薪' => $min_salary . '-' . $max_salary . '千', '实际年薪' => $send_user_min_salary . '千以上', '分值' => $score]; } elseif ($send_user_min_salary > $max_salary) { return ['code' => 0, '期望年薪' => $min_salary . '-' . $max_salary . '千', '实际年薪' => $send_user_min_salary . '千以上', '分值' => $score]; } else { return ['code' => 0, '期望年薪' => $min_salary . '-' . $max_salary . '千', '实际年薪' => $send_user_min_salary . '千以上', '分值' => $score]; } } } else { return ['code' => 0, '期望年薪' => $min_salary . '-' . $max_salary . '千', '实际年薪平均数' => "未设置", '分值' => 0]; } } else { if ($send_user->income) { return ['code' => 0, '期望年薪' => "未设置", '实际年薪平均数' => $send_user->income, '分值' => $score]; } else { return ['code' => 0, '期望年薪' => "未设置", '实际年薪平均数' => "未设置", '分值' => $score]; } } } /** * 计算动态学历分数 * @param $user * @param $send_user * @return array */ public function calculateDegreeScore($user, $send_user) { $score = 10; if ($user->mate_conditon) { $mate_conditon = json_decode($user->mate_conditon, true); if ($mate_conditon['degree'] != '学历不限') { if (!$send_user->degree) { return ['code' => 0, '要求学历' => $mate_conditon['degree'], '用户学历' => "未设置", '分值' => 0]; } else { //学历文字转为数字以备比较 $user_degree_number = self::degree[$mate_conditon['degree']]; $send_user_degree_number = self::degree[$send_user->degree]; if ($send_user_degree_number < $user_degree_number) { $sub_degree = $user_degree_number - $send_user_degree_number; $score = $score - $sub_degree; return ['code' => 0, '要求学历' => $mate_conditon['degree'], '用户学历' => $send_user->degree, '分值' => $score]; } elseif ($send_user_degree_number > $user_degree_number) { return ['code' => 0, '要求学历' => $mate_conditon['degree'], '用户学历' => $send_user->degree, '分值' => $score]; } else { return ['code' => 0, '要求学历' => $mate_conditon['degree'], '用户学历' => $send_user->degree, '分值' => $score]; } } } else { return ['code' => 0, '要求学历' => '未设置', '用户学历' => $send_user->degree, '分值' => $score]; } } else { return ['code' => 0, '要求学历' => '未设置', '用户学历' => $send_user->degree, '分值' => $score]; } } /** * 计算地域分数 * @param $user * @param $send_user * @return array */ public function calculateRegional($user, $send_user): array { $score = 10; if ($user->mate_conditon) { $mate_conditon = json_decode($user->mate_conditon, true); if ($mate_conditon['location'] == '所在地不限') { return ['code' => 0, '要求所在地' => '所在地不限', '用户所在地' => $send_user->city, '分值' => $score]; } elseif ($mate_conditon['location'] == '距离优先') { 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" ? 1 : 10; } elseif (($user->province != $send_user->province || empty($send_user->province)) && $user->resident_city == $send_user->resident_city) { //非同省、同家乡省市 $score += $user->type == "single" ? 2 : 20; } 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" ? 3 : 30; } 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" ? 3 : 30; } elseif (($user->province == $send_user->province && $user->city != $send_user->city) && $user->resident_city == $send_user->resident_city) { //同省非同市、同家乡市 $score += $user->type == "single" ? 4 : 40; } elseif ($user->city != $send_user->city && $user->resident_province != $send_user->resident_province) { //同市、同家乡省 $score += $user->type == "single" ? 4 : 40; } elseif (($user->province == $send_user->province && $user->city != $send_user->city) && $user->resident_city == $send_user->resident_city) { //同省非同市、同家乡市 $score += $user->type == "single" ? 5 : 50; } elseif ($user->city == $send_user->city && $user->resident_city == $send_user->resident_city) { //同省非同市、同家乡市 $score += $user->type == "single" ? 6 : 60; } return ['code' => 0, '要求' => '距离优先', '用户所在地' => $user->province, '分值' => $score]; } else { if ($mate_conditon['location'] == $user->province) { return ['code' => 0, '要求所在地' => $mate_conditon['location'], '用户所在地' => $user->province, '分值' => $score]; } else { return ['code' => 0, '要求所在地' => $mate_conditon['location'], '用户所在地' => $user->province, '分值' => 0]; } } } else { return ['code' => 0, '要求所在地' => '未要求', '用户所在地' => $user->province, '分值' => 10]; } } /** * 检测单身状态 * @param $user * @param $send_user * @return array * @throws \Calchen\LaravelDingtalkRobot\Exceptions\Exception */ public function checkType($user, $send_user): array { 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' => '']; } /** * 查询城市gps * @param $city_pin_yin * @param $user * @param $city * @return array|false|mixed */ public function getCityGps($city_pin_yin, $user, $city) { if (isset(self::$static_city_gps[$city_pin_yin])) { $city_gps = self::$static_city_gps[$city_pin_yin]; } else { $city_gps = json_decode(Redis::get('cityGps:' . $city_pin_yin), true); if (empty($city_gps)) { //Log::warning('[calculateRegional] 从数据据查询城市!!!'); $city_gps = CityGps::where('prefecture_level_city', $city)->select('prefecture_level_city', 'east_longitude', 'northern_latitude')->first(); if (!empty($city_gps)) { Redis::set('cityGps:' . $city_pin_yin, json_encode($city_gps)); self::$static_ai_reviews[$city_pin_yin] = $city_gps; } else { Log::warning('[calculateRegional] 百度查询!!!'); $request_url = 'http://api.map.baidu.com/geocoder?'; $request_address = 'address=地址'; $request_output = '&output=json'; $request_key = '&key=nKGpPpuOlcOA3nPy9jHj28kywEkn1N08'; $request_city = '&city=' . $user->city; $url = $request_url . $request_address . $request_output . $request_key . $request_city; $result = Http::post($url, null); if (!empty($result)) { $result = json_decode($result, true); if ($result['status'] == 'OK' && !empty($result['result']['location']['lng']) && !empty($result['result']['location']['lat'])) { if ($result['result']['location']['lng'] == '104.102' || $result['result']['location']['lat'] == '30.6545') { Log::warning('查询用户城市位置出错了!!! user_id = ' . $user->id . ' city = ' . $user->city); return ['code' => 1, 'msg' => '查询用户城市位置出错了!!! user_id = ' . $user->id . ' city = ' . $user->city . ',']; } $insert = [ 'east_longitude' => $result['result']['location']['lng'], 'northern_latitude' => $result['result']['location']['lat'], 'area_code' => '999999', 'province' => str_replace('省', '', $user->province), 'prefecture_level_city' => str_replace('市', '', $user->city), 'county_level_city' => str_replace('市', '', $user->city), 'ping_yin' => $city, //'ping_yin' =>str_replace( '-','',$pinyin->permalink($city)), 'telephone_area_code' => '999999', 'postal_code' => '999999', ]; CityGps::insert($insert); Redis::set('cityGps:' . $city_pin_yin, json_encode($insert)); $city_gps = $insert; self::$static_city_gps[$city_pin_yin] = $insert; } else { Log::warning('查不到用户城市位置 user_id = ' . $user->id . ' city = ' . $user->city); return ['code' => 1, 'msg' => '查不到用户城市位置 user_id = ' . $user->id . ' city = ' . $user->city . ',']; } } else { return ['code' => 1, 'msg' => '查不到用户城市位置 user_id = ' . $user->id . ' city = ' . $user->city . ',']; } } } else { self::$static_city_gps[$city_pin_yin] = $city_gps; } } $city_gps['code'] = 0; return $city_gps; } /** * 查询其它城市是否在范围内 * @param $city_pin_yin * @param $city_gps * @return array */ public function getOtherCity($city_pin_yin, $city_gps) { if (isset(self::$static_other_city[$city_pin_yin])) { $other_city = self::$static_other_city[$city_pin_yin]; } else { $other_city = json_decode(Redis::get('otherCity:' . $city_pin_yin)); if (empty($other_city)) { $point = $this->returnSquarePoint($city_gps['east_longitude'], $city_gps['northern_latitude'], 300); $other_city = CityGps::where('northern_latitude', '>', $point['right_bottom']['lat'])->where('northern_latitude', '<', $point['left_top']['lat']) ->where('east_longitude', '>', $point['left_top']['lng'])->where('east_longitude', '<', $point['right_bottom']['lng']) ->pluck('prefecture_level_city')->toArray(); if (!empty($other_city)) { $other_city = array_unique($other_city); Redis::set("otherCity:" . $city_pin_yin, json_encode(array_values($other_city))); self::$static_other_city[$city_pin_yin] = $other_city; } else { return ['code' => 1, 'msg' => '城市不在范围内,']; } } else { if (!is_array($other_city)) { $other_city = json_decode($other_city, true); } self::$static_other_city[$city_pin_yin] = $other_city; } } $other_city['code'] = 0; return $other_city; } /** *计算某个经纬度的周围某段距离的正方形的四个点 * @param $lng * @param $lat * @param float $distance * @return array 正方形的四个点的经纬度坐标 */ 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 $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 $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; } }