87 lines
2.5 KiB
PHP
87 lines
2.5 KiB
PHP
<?php
|
|||
|
|
|
||
|
|
namespace App\Services\Game;
|
||
|
|
|
||
|
|
use App\Models\Character;
|
||
|
|
use App\Models\GymSession;
|
||
|
|
|
||
|
|
class TrainingService
|
||
|
|
{
|
||
|
|
private const VALID_STATS = ['strength', 'defense', 'speed', 'dexterity'];
|
||
|
|
|
||
|
|
public function train(Character $character, string $stat): array
|
||
|
|
{
|
||
|
|
if (!in_array($stat, self::VALID_STATS, true)) {
|
||
|
|
return ['success' => false, 'message' => 'Invalid stat.', 'stat_value' => 0];
|
||
|
|
}
|
||
|
|
|
||
|
|
$energyCost = config('game.gym.energy_cost', 20);
|
||
|
|
$dailyCap = config('game.gym.daily_cap', 5);
|
||
|
|
$statGain = config('game.gym.stat_gain', 1);
|
||
|
|
|
||
|
|
if (!$character->hasEnergy($energyCost)) {
|
||
|
|
return [
|
||
|
|
'success' => false,
|
||
|
|
'message' => "Not enough energy ({$energyCost} required).",
|
||
|
|
'stat_value' => $character->$stat,
|
||
|
|
];
|
||
|
|
}
|
||
|
|
|
||
|
|
$sessionsToday = $this->getSessionsToday($character, $stat);
|
||
|
|
|
||
|
|
if ($sessionsToday >= $dailyCap) {
|
||
|
|
return [
|
||
|
|
'success' => false,
|
||
|
|
'message' => "Daily training cap reached for {$stat} ({$dailyCap} sessions).",
|
||
|
|
'stat_value' => $character->$stat,
|
||
|
|
];
|
||
|
|
}
|
||
|
|
|
||
|
|
// Deduct energy
|
||
|
|
$character->consumeEnergy($energyCost);
|
||
|
|
|
||
|
|
// Increment stat
|
||
|
|
$character->$stat += $statGain;
|
||
|
|
$character->save();
|
||
|
|
|
||
|
|
// Upsert gym_sessions row
|
||
|
|
$session = GymSession::firstOrNew([
|
||
|
|
'character_id' => $character->id,
|
||
|
|
'stat' => $stat,
|
||
|
|
]);
|
||
|
|
|
||
|
|
if (!$session->reset_date || $session->reset_date->lt(today())) {
|
||
|
|
$session->sessions_today = 0;
|
||
|
|
$session->reset_date = today();
|
||
|
|
}
|
||
|
|
|
||
|
|
$session->sessions_today += 1;
|
||
|
|
$session->save();
|
||
|
|
|
||
|
|
return [
|
||
|
|
'success' => true,
|
||
|
|
'message' => ucfirst($stat) . " increased to {$character->$stat}!",
|
||
|
|
'stat_value' => $character->$stat,
|
||
|
|
];
|
||
|
|
}
|
||
|
|
|
||
|
|
public function getSessionsToday(Character $character, string $stat): int
|
||
|
|
{
|
||
|
|
$session = GymSession::where('character_id', $character->id)
|
||
|
|
->where('stat', $stat)
|
||
|
|
->first();
|
||
|
|
|
||
|
|
if (!$session || $session->reset_date->lt(today())) {
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
return $session->sessions_today;
|
||
|
|
}
|
||
|
|
|
||
|
|
public function getSessionsRemaining(Character $character, string $stat): int
|
||
|
|
{
|
||
|
|
$cap = config('game.gym.daily_cap', 5);
|
||
|
|
return max(0, $cap - $this->getSessionsToday($character, $stat));
|
||
|
|
}
|
||
|
|
}
|