Files
BetiX/app/Http/Controllers/TrophyController.php
Dolo 0280278978
Some checks failed
linter / quality (push) Has been cancelled
tests / ci (8.4) (push) Has been cancelled
tests / ci (8.5) (push) Has been cancelled
Initialer Laravel Commit für BetiX
2026-04-04 18:01:50 +02:00

147 lines
6.0 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
namespace App\Http\Controllers;
use App\Models\GameBet;
use App\Models\User;
use App\Models\UserAchievement;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Inertia\Inertia;
class TrophyController extends Controller
{
/**
* All available achievements with their unlock conditions (for display).
*/
public static array $definitions = [
'first_bet' => ['title' => 'First Bet', 'desc' => 'Place your very first bet.', 'icon' => '🎲'],
'first_win' => ['title' => 'First Win', 'desc' => 'Win your first game.', 'icon' => '🏆'],
'big_winner' => ['title' => 'Big Winner', 'desc' => 'Land a 10× or higher multiplier.', 'icon' => '💥'],
'high_roller' => ['title' => 'High Roller', 'desc' => 'Wager 100+ BTX in total.', 'icon' => '💎'],
'frequent_player' => ['title' => 'Frequent Player', 'desc' => 'Place 50+ bets.', 'icon' => '🔥'],
'hundred_bets' => ['title' => 'Centurion', 'desc' => 'Place 100+ bets.', 'icon' => '⚡'],
'vault_user' => ['title' => 'Vault Guardian', 'desc' => 'Make your first vault deposit.', 'icon' => '🔒'],
'vip_level2' => ['title' => 'Rising Star', 'desc' => 'Reach VIP Level 2.', 'icon' => '⭐'],
'vip_level5' => ['title' => 'Elite', 'desc' => 'Reach VIP Level 5.', 'icon' => '👑'],
'guild_member' => ['title' => 'Team Player', 'desc' => 'Join a guild.', 'icon' => '🛡️'],
'promo_user' => ['title' => 'Promo Hunter', 'desc' => 'Redeem your first promo code.', 'icon' => '🎁'],
];
/**
* Trophy room page — show user's achievements + locked ones.
*/
public function index(Request $request)
{
$user = Auth::user();
abort_unless($user, 403);
// Sync achievements before showing
$this->syncAchievements($user);
$unlocked = UserAchievement::where('user_id', $user->id)
->pluck('unlocked_at', 'achievement_key');
$achievements = [];
foreach (self::$definitions as $key => $def) {
$achievements[] = [
'key' => $key,
'title' => $def['title'],
'description' => $def['desc'],
'icon' => $def['icon'],
'unlocked' => isset($unlocked[$key]),
'unlocked_at' => isset($unlocked[$key]) ? $unlocked[$key]->toIso8601String() : null,
];
}
// Sort: unlocked first, then locked
usort($achievements, fn($a, $b) => ($b['unlocked'] <=> $a['unlocked']));
return Inertia::render('Trophy', [
'achievements' => $achievements,
'total' => count(self::$definitions),
'unlocked' => $unlocked->count(),
]);
}
/**
* Trophy room for a specific user (public profiles only).
*/
public function show(Request $request, string $username)
{
$user = User::where('username', $username)->firstOrFail();
// Only show trophies for public profiles (or own profile)
if (!$user->is_public && Auth::id() !== $user->id) {
abort(403, 'This profile is private.');
}
$this->syncAchievements($user);
$unlocked = UserAchievement::where('user_id', $user->id)
->pluck('unlocked_at', 'achievement_key');
$achievements = [];
foreach (self::$definitions as $key => $def) {
$achievements[] = [
'key' => $key,
'title' => $def['title'],
'description' => $def['desc'],
'icon' => $def['icon'],
'unlocked' => isset($unlocked[$key]),
'unlocked_at' => isset($unlocked[$key]) ? $unlocked[$key]->toIso8601String() : null,
];
}
usort($achievements, fn($a, $b) => ($b['unlocked'] <=> $a['unlocked']));
return Inertia::render('Trophy', [
'achievements' => $achievements,
'total' => count(self::$definitions),
'unlocked' => $unlocked->count(),
'profileUser' => ['username' => $user->username, 'avatar' => $user->avatar],
]);
}
/**
* Check and unlock achievements for the given user.
*/
public function syncAchievements(\App\Models\User $user): void
{
$bets = GameBet::where('user_id', $user->id);
$betCount = $bets->count();
$totalWager = $bets->sum('wager_amount');
$maxMulti = $bets->max('payout_multiplier') ?? 0;
$hasWin = $bets->where('payout_amount', '>', 0)->exists();
$toUnlock = [];
if ($betCount >= 1) $toUnlock[] = 'first_bet';
if ($hasWin) $toUnlock[] = 'first_win';
if ($maxMulti >= 10) $toUnlock[] = 'big_winner';
if ($totalWager >= 100) $toUnlock[] = 'high_roller';
if ($betCount >= 50) $toUnlock[] = 'frequent_player';
if ($betCount >= 100) $toUnlock[] = 'hundred_bets';
if ($user->vip_level >= 2) $toUnlock[] = 'vip_level2';
if ($user->vip_level >= 5) $toUnlock[] = 'vip_level5';
if ($user->guildMember()->exists()) $toUnlock[] = 'guild_member';
// Vault usage
if (\App\Models\WalletTransfer::where('user_id', $user->id)->where('type', 'deposit')->exists()) {
$toUnlock[] = 'vault_user';
}
// Promo usage
if (\App\Models\PromoUsage::where('user_id', $user->id)->exists()) {
$toUnlock[] = 'promo_user';
}
foreach ($toUnlock as $key) {
UserAchievement::firstOrCreate(
['user_id' => $user->id, 'achievement_key' => $key],
['unlocked_at' => now()]
);
}
}
}