- Add database migrations for market_listings, missions and character cosmetics - Create controllers for marketplace, missions, presence and character customization - Implement admin world dashboard with live platform metrics - Add feature tests for world functionality - Include phase 2 design documents and gap analysis
82 lines
3.0 KiB
PHP
Executable File
82 lines
3.0 KiB
PHP
Executable File
<?php
|
|
|
|
namespace App\Http\Controllers\Web\Admin;
|
|
|
|
use App\Http\Controllers\Controller;
|
|
use App\Models\Building;
|
|
use App\Models\Character;
|
|
use App\Models\CharacterMessage;
|
|
use App\Models\City;
|
|
use App\Models\Job;
|
|
use App\Models\MarketListing;
|
|
use App\Models\Mission;
|
|
use App\Models\Store;
|
|
use App\Models\Transaction;
|
|
use App\Models\User;
|
|
use App\Models\UserConsent;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\View\View;
|
|
|
|
/**
|
|
* Administrator world dashboard and metrics.
|
|
*
|
|
* Aggregates live city health: citizens, economy, constructions, missions
|
|
* and marketplace activity so operators can steer the persistent world.
|
|
*/
|
|
class AdminWorldController extends Controller
|
|
{
|
|
/**
|
|
* HTML dashboard for the admin area.
|
|
*/
|
|
public function index(Request $request): View
|
|
{
|
|
abort_unless($request->user()?->isAdmin(), 403);
|
|
|
|
return view('admin.world.index', [
|
|
'metrics' => $this->metrics(),
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* JSON metrics (also used by the report command).
|
|
*/
|
|
public function metrics(): array
|
|
{
|
|
return [
|
|
'users' => [
|
|
'total' => User::query()->count(),
|
|
'pending' => User::query()->where('status', User::STATUS_PENDING)->count(),
|
|
'active' => User::query()->where('status', User::STATUS_ACTIVE)->count(),
|
|
'banned' => User::query()->where('status', User::STATUS_BANNED)->count(),
|
|
'consents' => UserConsent::query()->count(),
|
|
],
|
|
'cities' => City::query()->count(),
|
|
'characters' => [
|
|
'total' => Character::query()->count(),
|
|
'online' => Character::query()->where('is_online', true)->count(),
|
|
'hospitalized' => Character::query()->where('state', Character::STATE_HOSPITAL)->count(),
|
|
'avg_health' => (int) round(Character::query()->avg('health') ?? 0),
|
|
'avg_education' => (int) round(Character::query()->avg('education') ?? 0),
|
|
'total_money' => round((float) Character::query()->sum('money'), 2),
|
|
],
|
|
'world' => [
|
|
'stores' => Store::query()->count(),
|
|
'buildings' => Building::query()->count(),
|
|
'houses_complete' => Building::query()->where('type', 'house')->where('is_complete', true)->count(),
|
|
'jobs' => Job::query()->count(),
|
|
'messages' => CharacterMessage::query()->count(),
|
|
'transactions' => Transaction::query()->count(),
|
|
'transaction_volume' => round((float) Transaction::query()->sum('amount'), 2),
|
|
],
|
|
'market' => [
|
|
'listings' => MarketListing::query()->where('is_active', true)->count(),
|
|
],
|
|
'missions' => [
|
|
'active' => Mission::query()->where('is_active', true)->count(),
|
|
'completed' => DB::table('character_missions')->where('is_completed', true)->count(),
|
|
],
|
|
];
|
|
}
|
|
}
|