feature/api-stats #82

Merged
FernandoJVideira merged 4 commits from feature/api-stats into develop 2025-12-29 19:08:47 +00:00
5 changed files with 113 additions and 5 deletions
@@ -53,6 +53,10 @@ class AuthController extends Controller
if (User::where('email', $request->email)->exists()) { if (User::where('email', $request->email)->exists()) {
return response()->json(['message' => 'Email already registered'], 409); return response()->json(['message' => 'Email already registered'], 409);
} }
if (User::where('nickname', $request->nickname)->exists()) {
return response()->json(['message' => 'Nickname already registered'], 409);
}
$user = User::create([ $user = User::create([
'email' => $request->email, 'email' => $request->email,
+17 -4
View File
@@ -3,6 +3,12 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use App\Models\User;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
class ProfileController extends Controller class ProfileController extends Controller
{ {
@@ -52,7 +58,7 @@ class ProfileController extends Controller
$user = $request->user(); $user = $request->user();
if (!\Hash::check($request->current_password, $user->password)) { if (!Hash::check($request->current_password, $user->password)) {
return response()->json( return response()->json(
[ [
"message" => "Current password is incorrect", "message" => "Current password is incorrect",
@@ -61,7 +67,7 @@ class ProfileController extends Controller
); );
} }
$user->password = \Hash::make($request->new_password); $user->password = Hash::make($request->new_password);
$user->save(); $user->save();
return response()->json([ return response()->json([
@@ -69,6 +75,13 @@ class ProfileController extends Controller
]); ]);
} }
public function getCoins(Request $request)
{
return response()->json([
'coins' => $request->user()->coins_balance
]);
}
public function updateAvatar(Request $request) public function updateAvatar(Request $request)
{ {
$request->validate([ $request->validate([
@@ -78,7 +91,7 @@ class ProfileController extends Controller
$user = $request->user(); $user = $request->user();
if ($user->photo_avatar_filename) { if ($user->photo_avatar_filename) {
\Storage::disk("public")->delete( Storage::disk("public")->delete(
"photos_avatars/" . $user->photo_avatar_filename, "photos_avatars/" . $user->photo_avatar_filename,
); );
} }
@@ -87,7 +100,7 @@ class ProfileController extends Controller
$filename = $filename =
str_pad($user->id, 5, "0", STR_PAD_LEFT) . str_pad($user->id, 5, "0", STR_PAD_LEFT) .
"_" . "_" .
\Str::random(10) . Str::random(10) .
"." . "." .
$file->extension(); $file->extension();
$file->storeAs("photos_avatars", $filename, "public"); $file->storeAs("photos_avatars", $filename, "public");
@@ -0,0 +1,76 @@
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use App\Models\Game;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
class StatisticsController extends Controller
{
public function getPublicStats()
{
$totalPlayers = User::where('type', 'P')->count();
$totalGames = Game::where('status', 'Ended')->count();
$activeGames = Game::where('status', 'Playing')->count();
return response()->json([
'total_players' => $totalPlayers,
'total_games' => $totalGames,
'active_games' => $activeGames,
]);
}
public function getLeaderboard(Request $request)
{
$type = $request->query('type');
$query = User::where('type', 'P')
->withCount(['wonGames' => function ($query) use ($type) {
if ($type) {
$query->where('type', $type);
}
}])
->orderBy('won_games_count', 'desc')
->take(10);
$leaderboard = $query->get(['id', 'nickname', 'photo_avatar_filename']);
return response()->json($leaderboard);
}
public function getPersonalStats(Request $request)
{
$user = $request->user();
$totalGames = Game::where('status', 'Ended')
->where(function ($q) use ($user) {
$q->where('player1_user_id', $user->id)
->orWhere('player2_user_id', $user->id);
})
->count();
$totalWins = Game::where('status', 'Ended')
->where('winner_user_id', $user->id)
->count();
$totalLosses = $totalGames - $totalWins; // Simplest math
$winRate = 0;
if ($totalGames > 0) {
$winRate = round(($totalWins / $totalGames) * 100, 1);
}
return response()->json([
'nickname' => $user->nickname,
'total_games' => $totalGames,
'total_wins' => $totalWins,
'total_losses' => $totalLosses,
'win_rate' => $winRate . '%',
'current_balance' => $user->coins_balance, // Extra info
]);
}
}
+10
View File
@@ -48,4 +48,14 @@ class User extends Authenticatable
'blocked' => 'boolean', 'blocked' => 'boolean',
'deleted_at' => 'datetime', 'deleted_at' => 'datetime',
]; ];
public function wonGames()
{
return $this->hasMany(Game::class, 'winner_user_id');
}
public function games()
{
return $this->hasMany(Game::class, 'player1_user_id')->orWhere('player2_user_id', $this->id);
}
} }
+6 -1
View File
@@ -5,6 +5,7 @@ use App\Http\Controllers\GameController;
use App\Http\Controllers\MatchController; use App\Http\Controllers\MatchController;
use App\Http\Controllers\ProfileController; use App\Http\Controllers\ProfileController;
use App\Http\Controllers\UserController; use App\Http\Controllers\UserController;
use App\Http\Controllers\StatisticsController;
use Illuminate\Support\Facades\Route; use Illuminate\Support\Facades\Route;
Route::prefix('v1')->group(function () { Route::prefix('v1')->group(function () {
@@ -12,14 +13,18 @@ Route::prefix('v1')->group(function () {
Route::post('/login', [AuthController::class, 'login']); Route::post('/login', [AuthController::class, 'login']);
Route::post('/register', [AuthController::class, 'register']); Route::post('/register', [AuthController::class, 'register']);
Route::get('/statistics/public', [StatisticsController::class, 'getPublicStats']);
Route::get('/leaderboard', [StatisticsController::class, 'getLeaderboard']);
// Authenticated Routes // Authenticated Routes
Route::middleware(['auth:sanctum', 'throttle:60,1'])->group(function () { Route::middleware(['auth:sanctum', 'throttle:60,1'])->group(function () {
Route::post('/logout', [AuthController::class, 'logout']); Route::post('/logout', [AuthController::class, 'logout']);
Route::get('/statistics/me', [StatisticsController::class, 'getPersonalStats']);
Route::prefix('users/me')->group(function () { Route::prefix('users/me')->group(function () {
Route::get('/', [ProfileController::class, 'show']); Route::get('/', [ProfileController::class, 'show']);
Route::put('/', [ProfileController::class, 'update']); Route::put('/', [ProfileController::class, 'update']);
Route::delete('/', [ProfileController::class, 'destroy']); Route::delete('/', [ProfileController::class, 'destroy']);
Route::get('/coins', [ProfileController::class, 'getCoins']);
Route::put('/password', [ Route::put('/password', [
ProfileController::class, ProfileController::class,
'updatePassword', 'updatePassword',