Files
water_new/modules/User/Facades/UserSign.php

309 lines
8.7 KiB
PHP

<?php
namespace Modules\User\Facades;
use Carbon\Carbon;
use DateTime;
use Exception;
use Illuminate\Support\HigherOrderCollectionProxy;
use Modules\User\Models\SignConfig;
use Modules\User\Models\SignLog;
use Modules\User\Models\User;
/**
* 用户签到
* Class UserSign
*
* @package Modules\User\Facades
*/
class UserSign
{
/**
* @param User $user
* @return array
*/
public static function signIn(User $user, $date = ''): array
{
try {
$date = Carbon::parse($date);//签到日期
$params = SignConfig::getParams();
if (!isset($params['open'])) {
throw new Exception('签到功能未开启');
}
if (! self::canSign($user, $date)) {
throw new Exception(self::getNotSignText($user, $date));
}
$continue_days = $user->sign->continue_days;
$counts = $user->sign->counts;
if (SignLog::where('user_id', $user->id)
->whereDate('date', (clone $date)->subDay()->toDateString())
->exists()) {
$continue_days++;
} else {
$continue_days = 1;
}
$crystals = self::getSignCrystal($continue_days);
$rule_name = $params['rule_name'];
$str = "{$continue_days}天签到";
if ($crystals > 0) {
$user->account->rule($rule_name, 0, false, [
'frozen_at' => now()->toDateTimeString(),
'settle_at' => now()->toDateTimeString(),
'remark' => '第'.$continue_days.'天签到',
]);
$str .= ",获得{$crystals}水滴"."\n";
// $str .= '第'.$continue_days.'天签到';
}
$task_crystals = self::getTaskCrystal($continue_days);
if ($task_crystals > 0) {
// $user->account->rule($rule_name, $task_crystals, true, [
// 'frozen_at' => now()->toDateTimeString(),
// 'settle_at' => now()->toDateTimeString(),
// 'remark' => '连续签到'.$continue_days.'天',
// ]);
// $str .= '连续签到'.$continue_days.'天,获得水晶'.$task_crystals;
$str .= '连续签到'.$continue_days.'天';
}
$user->sign->update([
'continue_days' => $continue_days,
'counts' => ++$counts,
'last_sign_at' => $date,
]);
SignLog::create([
'user_id' => $user->id,
'date' => $date,
'type' => 0,
]);
return [true, $str];
} catch (Exception $e) {
return [false, $e->getMessage()];
}
}
/**
* 返回连续签到额外任务
*
* @param int $continue_days
* @return int
*/
public static function getTaskCrystal(int $continue_days = 1): int
{
$tasks = SignConfig::getTasks();
$task = $tasks->firstWhere('day', $continue_days);
return $task['number'] ?? 0;
}
public static function getNextTaskCrystal($continue_days = 1)
{
$tasks = SignConfig::getTasks();
return $tasks->where('day', ' > ', $continue_days)
->sortBy('day')
->first();
}
/**
* 返回签到奖励
*
* @param int $continue_days
* @return HigherOrderCollectionProxy|int|mixed
*/
public static function getSignCrystal(int &$continue_days = 1)
{
$params = SignConfig::getParams();
$crystals = 0;
switch ($params['type']) {
case 'single':
$crystals = $params['single_number'];
break;
case 'continuous':
$crystals = (int) $params['continuous_base'] + (int) bcmul($continue_days - 1,
$params['continuous_incremental'],
0);
break;
case 'cycle':
if ($continue_days > $params['cycle_day']) {
$continue_days -= $params['cycle_day'];
}
$crystals = (int) $params['cycle_base'] + (int) bcmul($continue_days - 1, $params['cycle_incremental'],
0);
break;
}
return $crystals;
}
/**
* Notes : 某一天是否可签到
*
* @Date : 2021/5/28 3:25 下午
* @Author : <Jason.C>
* @param User $user
* @param Carbon $date
* @return bool
*/
public static function canSign(User $user, DateTime $date): bool
{
$identityMiddle = $user->identityMiddle()->first();
$start_at = $identityMiddle->started_at;
if (! $start_at) {
$start_at = $identityMiddle->created_at;
}
return $identityMiddle->identity->order > 1 &&
Carbon::parse($date)->endOfDay()->gt($start_at) &&
! $user->IsSign($date) &&
$date->isToday();
}
/**
* Notes: 是否可以补签
*
* @Author: 玄尘
* @Date: 2022/8/12 8:51
* @param User $user
* @param DateTime $date
* @return bool
*/
public static function canReSign(User $user, DateTime $date): bool
{
$identityMiddle = $user->identityMiddle()->first();
$start_at = $identityMiddle->started_at;
if (! $start_at) {
$start_at = $identityMiddle->created_at;
}
return ! $user->IsSign($date) &&
now()->endOfDay()->gt($date) &&
! $date->isToday() &&
Carbon::parse($date)->endOfDay()->gt($start_at);
}
/**
* Notes: 获取不可打卡的信息
*
* @Author: 玄尘
* @Date: 2022/8/10 13:18
*/
public static function getNotSignText(User $user, DateTime $date)
{
$identityMiddle = $user->identityMiddle()->first();
if (SignLog::where('user_id', $user->id)->whereDate('date', $date)->exists()) {
return '今日已打卡';
}
if ($identityMiddle->identity->order < 2) {
return '未开通会员';
}
$started_at = $identityMiddle->started_at;
if (! $started_at) {
$started_at = $identityMiddle->created_at;
}
if ($started_at->gt(Carbon::parse($date)->startOfDay())) {
return '当前时间还未开通会员';
}
}
/**
* Notes : 补签
*
* @Date : 2021/5/28 3:15 下午
* @Author : <Jason.C>
* @param User $user
* @param DateTime $date
* @return bool
* @throws Exception
*/
public static function replenish(User $user, DateTime $date): array
{
if (! self::canReSign($user, $date)) {
throw new Exception(self::getNotSignText($user, $date));
}
$params = SignConfig::getParams();
$continue_days = $user->sign->continue_days;
$crystals = self::getSignCrystal($continue_days);
$rule_name = $params['rule_name'];
$str = $date->format('Y-m-d')."号补签";
if ($crystals > 0) {
$user->account->rule($rule_name, 0, false, [
'frozen_at' => now()->toDateTimeString(),
'settle_at' => now()->toDateTimeString(),
'remark' => now()->toDateTimeString().'天补签到',
]);
$str .= ",获得{$crystals}水滴"."\n";
}
$counts = $user->sign->counts;
$user->sign->update([
'counts' => ++$counts,
]);
$log = SignLog::create([
'user_id' => $user->id,
'date' => $date,
'type' => 1,
]);
self::recalculateContinueDays($user);
return [true, $str];
}
/**
* Notes: 重新计算连续签到日期
*
* @Author: 玄尘
* @Date: 2022/8/4 9:34
*/
public static function recalculateContinueDays(User $user)
{
$reset_at = $user->sign->reset_at;
$days = SignLog::query()
->byUser($user)
->when($reset_at, function ($q) use ($reset_at) {
$q->where('date', '>=', $reset_at);
})
->latest('date')
->pluck('date');
$continue_days = 1;
foreach ($days as $key => $day) {
if (isset($days[$key + 1])) {
if ($day->subDay()->isSameDay($days[$key + 1])) {
$continue_days++;
} else {
break;
}
}
}
$user->sign->update([
'continue_days' => max($continue_days, 1),
'counts' => $user->signLogs()->count()
]);
return true;
}
}