mirror of
https://github.com/pacnpal/thrillwiki_laravel.git
synced 2025-12-20 09:11:10 -05:00
Add models, enums, and services for user roles, theme preferences, slug history, and ID generation
This commit is contained in:
41
app/Services/IdGenerator.php
Normal file
41
app/Services/IdGenerator.php
Normal file
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class IdGenerator
|
||||
{
|
||||
/**
|
||||
* Generate a random ID starting at 4 digits, expanding to 5 if needed
|
||||
*
|
||||
* @param string $model Model class name
|
||||
* @param string $field Field to check for uniqueness
|
||||
* @return string
|
||||
*/
|
||||
public static function generate(string $model, string $field): string
|
||||
{
|
||||
$attempts = 0;
|
||||
$maxAttempts = 10;
|
||||
|
||||
while ($attempts < $maxAttempts) {
|
||||
// Try 4 digits first
|
||||
if ($attempts < 5) {
|
||||
$id = (string) random_int(1000, 9999);
|
||||
} else {
|
||||
// Try 5 digits if all 4-digit numbers are taken
|
||||
$id = (string) random_int(10000, 99999);
|
||||
}
|
||||
|
||||
if (!$model::where($field, $id)->exists()) {
|
||||
return $id;
|
||||
}
|
||||
|
||||
$attempts++;
|
||||
}
|
||||
|
||||
// If we get here, try a completely random string as fallback
|
||||
return Str::random(10);
|
||||
}
|
||||
}
|
||||
217
app/Services/StatisticsCacheService.php
Normal file
217
app/Services/StatisticsCacheService.php
Normal file
@@ -0,0 +1,217 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use App\Models\Park;
|
||||
use App\Models\ParkArea;
|
||||
use App\Models\Operator;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class StatisticsCacheService
|
||||
{
|
||||
/**
|
||||
* Cache TTL in seconds (24 hours).
|
||||
*/
|
||||
protected const CACHE_TTL = 86400;
|
||||
|
||||
/**
|
||||
* Cache key prefixes.
|
||||
*/
|
||||
protected const AREA_PREFIX = 'stats:area:';
|
||||
protected const PARK_PREFIX = 'stats:park:';
|
||||
protected const OPERATOR_PREFIX = 'stats:operator:';
|
||||
|
||||
/**
|
||||
* Cache area statistics.
|
||||
*/
|
||||
public function cacheAreaStatistics(ParkArea $area): void
|
||||
{
|
||||
try {
|
||||
Cache::put(
|
||||
$this->getAreaKey($area),
|
||||
[
|
||||
'ride_distribution' => $area->ride_distribution,
|
||||
'daily_capacity' => $area->formatted_daily_capacity,
|
||||
'rating' => $area->rating_display,
|
||||
'wait_time' => $area->formatted_peak_wait_time,
|
||||
'historical' => $area->historical_stats,
|
||||
'updated_at' => now(),
|
||||
],
|
||||
static::CACHE_TTL
|
||||
);
|
||||
|
||||
Log::info("Cached statistics for area {$area->id}");
|
||||
} catch (\Exception $e) {
|
||||
Log::error("Failed to cache area statistics: {$e->getMessage()}");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Cache park statistics.
|
||||
*/
|
||||
public function cacheParkStatistics(Park $park): void
|
||||
{
|
||||
try {
|
||||
Cache::put(
|
||||
$this->getParkKey($park),
|
||||
[
|
||||
'area_distribution' => $park->area_distribution,
|
||||
'ride_distribution' => $park->ride_distribution,
|
||||
'daily_capacity' => $park->formatted_daily_capacity,
|
||||
'rating' => $park->rating_display,
|
||||
'wait_time' => $park->formatted_wait_time,
|
||||
'historical' => $park->historical_stats,
|
||||
'performance' => $park->performance_metrics,
|
||||
'updated_at' => now(),
|
||||
],
|
||||
static::CACHE_TTL
|
||||
);
|
||||
|
||||
Log::info("Cached statistics for park {$park->id}");
|
||||
} catch (\Exception $e) {
|
||||
Log::error("Failed to cache park statistics: {$e->getMessage()}");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Cache operator statistics.
|
||||
*/
|
||||
public function cacheOperatorStatistics(Operator $operator): void
|
||||
{
|
||||
try {
|
||||
Cache::put(
|
||||
$this->getOperatorKey($operator),
|
||||
[
|
||||
'park_count' => $operator->total_parks,
|
||||
'operating_parks' => $operator->operating_parks,
|
||||
'closed_parks' => $operator->closed_parks,
|
||||
'total_rides' => $operator->total_rides,
|
||||
'total_coasters' => $operator->total_coasters,
|
||||
'average_rating' => $operator->average_rating,
|
||||
'total_capacity' => $operator->total_daily_capacity,
|
||||
'updated_at' => now(),
|
||||
],
|
||||
static::CACHE_TTL
|
||||
);
|
||||
|
||||
Log::info("Cached statistics for operator {$operator->id}");
|
||||
} catch (\Exception $e) {
|
||||
Log::error("Failed to cache operator statistics: {$e->getMessage()}");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get cached area statistics.
|
||||
*
|
||||
* @return array<string, mixed>|null
|
||||
*/
|
||||
public function getAreaStatistics(ParkArea $area): ?array
|
||||
{
|
||||
return Cache::get($this->getAreaKey($area));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get cached park statistics.
|
||||
*
|
||||
* @return array<string, mixed>|null
|
||||
*/
|
||||
public function getParkStatistics(Park $park): ?array
|
||||
{
|
||||
return Cache::get($this->getParkKey($park));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get cached operator statistics.
|
||||
*
|
||||
* @return array<string, mixed>|null
|
||||
*/
|
||||
public function getOperatorStatistics(Operator $operator): ?array
|
||||
{
|
||||
return Cache::get($this->getOperatorKey($operator));
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidate area statistics cache.
|
||||
*/
|
||||
public function invalidateAreaCache(ParkArea $area): void
|
||||
{
|
||||
Cache::forget($this->getAreaKey($area));
|
||||
Log::info("Invalidated cache for area {$area->id}");
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidate park statistics cache.
|
||||
*/
|
||||
public function invalidateParkCache(Park $park): void
|
||||
{
|
||||
Cache::forget($this->getParkKey($park));
|
||||
Log::info("Invalidated cache for park {$park->id}");
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidate operator statistics cache.
|
||||
*/
|
||||
public function invalidateOperatorCache(Operator $operator): void
|
||||
{
|
||||
Cache::forget($this->getOperatorKey($operator));
|
||||
Log::info("Invalidated cache for operator {$operator->id}");
|
||||
}
|
||||
|
||||
/**
|
||||
* Warm up caches for all entities.
|
||||
*/
|
||||
public function warmCaches(): void
|
||||
{
|
||||
try {
|
||||
// Cache area statistics
|
||||
ParkArea::chunk(100, function ($areas) {
|
||||
foreach ($areas as $area) {
|
||||
$this->cacheAreaStatistics($area);
|
||||
}
|
||||
});
|
||||
|
||||
// Cache park statistics
|
||||
Park::chunk(100, function ($parks) {
|
||||
foreach ($parks as $park) {
|
||||
$this->cacheParkStatistics($park);
|
||||
}
|
||||
});
|
||||
|
||||
// Cache operator statistics
|
||||
Operator::chunk(100, function ($operators) {
|
||||
foreach ($operators as $operator) {
|
||||
$this->cacheOperatorStatistics($operator);
|
||||
}
|
||||
});
|
||||
|
||||
Log::info('Successfully warmed up all statistics caches');
|
||||
} catch (\Exception $e) {
|
||||
Log::error("Failed to warm up caches: {$e->getMessage()}");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get cache key for area.
|
||||
*/
|
||||
protected function getAreaKey(ParkArea $area): string
|
||||
{
|
||||
return static::AREA_PREFIX . $area->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get cache key for park.
|
||||
*/
|
||||
protected function getParkKey(Park $park): string
|
||||
{
|
||||
return static::PARK_PREFIX . $park->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get cache key for operator.
|
||||
*/
|
||||
protected function getOperatorKey(Operator $operator): string
|
||||
{
|
||||
return static::OPERATOR_PREFIX . $operator->id;
|
||||
}
|
||||
}
|
||||
162
app/Services/StatisticsRollupService.php
Normal file
162
app/Services/StatisticsRollupService.php
Normal file
@@ -0,0 +1,162 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use App\Models\Park;
|
||||
use App\Models\ParkArea;
|
||||
use App\Models\Operator;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class StatisticsRollupService
|
||||
{
|
||||
/**
|
||||
* Update statistics for a specific area.
|
||||
*/
|
||||
public function updateAreaStatistics(ParkArea $area): void
|
||||
{
|
||||
DB::transaction(function () use ($area) {
|
||||
// Update area statistics (will be implemented with Rides system)
|
||||
// For now, we'll just ensure the area triggers park updates
|
||||
$this->updateParkStatistics($area->park);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Update statistics for a specific park.
|
||||
*/
|
||||
public function updateParkStatistics(Park $park): void
|
||||
{
|
||||
DB::transaction(function () use ($park) {
|
||||
// Update area counts
|
||||
$park->updateAreaCounts();
|
||||
|
||||
// Update ride statistics
|
||||
$park->updateRideStatistics();
|
||||
|
||||
// Update visitor statistics
|
||||
$park->updateVisitorStats();
|
||||
|
||||
// Update operator statistics
|
||||
if ($park->operator) {
|
||||
$this->updateOperatorStatistics($park->operator);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Update statistics for a specific operator.
|
||||
*/
|
||||
public function updateOperatorStatistics(Operator $operator): void
|
||||
{
|
||||
DB::transaction(function () use ($operator) {
|
||||
$parks = $operator->parks;
|
||||
|
||||
// Update park counts
|
||||
$operator->update([
|
||||
'total_parks' => $parks->count(),
|
||||
'operating_parks' => $parks->operating()->count(),
|
||||
'closed_parks' => $parks->closed()->count(),
|
||||
]);
|
||||
|
||||
// Update ride totals
|
||||
$operator->update([
|
||||
'total_rides' => $parks->sum('total_rides'),
|
||||
'total_coasters' => $parks->sum('total_coasters'),
|
||||
'total_flat_rides' => $parks->sum('total_flat_rides'),
|
||||
'total_water_rides' => $parks->sum('total_water_rides'),
|
||||
]);
|
||||
|
||||
// Update performance metrics
|
||||
$ratedParks = $parks->whereNotNull('average_rating');
|
||||
if ($ratedParks->count() > 0) {
|
||||
$operator->update([
|
||||
'average_rating' => $ratedParks->avg('average_rating'),
|
||||
'total_daily_capacity' => $parks->sum('total_daily_capacity'),
|
||||
'average_utilization' => $parks->avg('utilization_rate'),
|
||||
]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Update all statistics in the system.
|
||||
*/
|
||||
public function refreshAllStatistics(): void
|
||||
{
|
||||
DB::transaction(function () {
|
||||
// Update all areas first
|
||||
ParkArea::chunk(100, function ($areas) {
|
||||
foreach ($areas as $area) {
|
||||
// Area statistics will be implemented with Rides system
|
||||
}
|
||||
});
|
||||
|
||||
// Update all parks
|
||||
Park::chunk(100, function ($parks) {
|
||||
foreach ($parks as $park) {
|
||||
$this->updateParkStatistics($park);
|
||||
}
|
||||
});
|
||||
|
||||
// Update all operators
|
||||
Operator::chunk(100, function ($operators) {
|
||||
foreach ($operators as $operator) {
|
||||
$this->updateOperatorStatistics($operator);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedule regular statistics updates.
|
||||
*/
|
||||
public function scheduleUpdates(): void
|
||||
{
|
||||
// This method will be called by the scheduler
|
||||
$this->refreshAllStatistics();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle ride addition event.
|
||||
*/
|
||||
public function handleRideAdded(ParkArea $area): void
|
||||
{
|
||||
DB::transaction(function () use ($area) {
|
||||
$area->recordNewRide();
|
||||
$this->updateAreaStatistics($area);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle ride retirement event.
|
||||
*/
|
||||
public function handleRideRetired(ParkArea $area): void
|
||||
{
|
||||
DB::transaction(function () use ($area) {
|
||||
$area->recordRetirement();
|
||||
$this->updateAreaStatistics($area);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle park expansion event.
|
||||
*/
|
||||
public function handleParkExpansion(Park $park): void
|
||||
{
|
||||
DB::transaction(function () use ($park) {
|
||||
$park->recordExpansion();
|
||||
$this->updateParkStatistics($park);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle major update event.
|
||||
*/
|
||||
public function handleMajorUpdate(Park $park): void
|
||||
{
|
||||
DB::transaction(function () use ($park) {
|
||||
$park->recordMajorUpdate();
|
||||
$this->updateParkStatistics($park);
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user