64 lines
2.1 KiB
PHP
64 lines
2.1 KiB
PHP
<?php
|
||
|
||
namespace App\Services;
|
||
|
||
use App\Models\Achievement;
|
||
use App\Models\UserAchievement;
|
||
use App\Models\User;
|
||
use App\Models\ContinueWatching;
|
||
use App\Models\Watchlist;
|
||
use Illuminate\Support\Facades\DB;
|
||
|
||
class AchievementService
|
||
{
|
||
/**
|
||
* Kullanıcının kazanması gereken başarımları kontrol et ve ver.
|
||
* Yeni kazanılan başarımları döndürür (popup için).
|
||
*/
|
||
public static function check(User $user): array
|
||
{
|
||
$allAchievements = Achievement::all();
|
||
$earned = UserAchievement::where('user_id', $user->id)->pluck('achievement_id')->toArray();
|
||
|
||
$newlyEarned = [];
|
||
|
||
foreach ($allAchievements as $ach) {
|
||
if (in_array($ach->id, $earned)) continue;
|
||
|
||
$met = match ($ach->condition_type) {
|
||
'episodes_watched' => self::episodesWatched($user) >= $ach->condition_value,
|
||
'hours_watched' => self::hoursWatched($user) >= $ach->condition_value,
|
||
'watchlist_count' => Watchlist::where('user_id', $user->id)->count() >= $ach->condition_value,
|
||
'anime_rated' => DB::table('anime_ratings')->where('user_id', $user->id)->count() >= $ach->condition_value,
|
||
'request_sent' => DB::table('anime_requests')->where('user_id', $user->id)->count() >= $ach->condition_value,
|
||
'first_login' => true,
|
||
default => false,
|
||
};
|
||
|
||
if ($met) {
|
||
UserAchievement::firstOrCreate([
|
||
'user_id' => $user->id,
|
||
'achievement_id' => $ach->id,
|
||
], ['earned_at' => now()]);
|
||
$newlyEarned[] = $ach;
|
||
}
|
||
}
|
||
|
||
return $newlyEarned;
|
||
}
|
||
|
||
private static function episodesWatched(User $user): int
|
||
{
|
||
return ContinueWatching::where('user_id', $user->id)
|
||
->where('percent_complete', '>=', 70)
|
||
->count();
|
||
}
|
||
|
||
private static function hoursWatched(User $user): float
|
||
{
|
||
return round(
|
||
ContinueWatching::where('user_id', $user->id)->sum('seconds_watched') / 3600, 1
|
||
);
|
||
}
|
||
}
|