<?php namespace App\Games; use App\Constants\Status; use App\Models\Game as GameModel; use App\Models\GameLog; use App\Models\GameplayBonusLog; use App\Models\Transaction; use App\Models\User; use Illuminate\Http\Request; use Illuminate\Support\Facades\Validator; abstract class Game { private $globalValidationRule = [ 'invest' => 'required|numeric|gt:0', ]; protected $extraValidationRule = []; protected $exceptValidationRule = []; protected $extraEndValidationRule = []; protected $alias; protected $game; protected $request; protected $user; protected $resultShowOnStart = true; protected $extraResponseOnStart = []; protected $extraResponseOnEnd = []; protected $userSelect; protected $hasCustomCompleteLogic = false; protected $extraResponseOnWin = []; public $demoPlay = false; public $fromApi = false; public function __construct() { $this->request = request(); $this->user = auth()->user(); $this->game = GameModel::active()->where('alias', $this->alias)->first(); $this->userSelect = $this->request?->choose ?? ''; } public function play() { $user = $this->user; if (!$this->game) { if ($this->fromApi) { $notify[] = 'Game not found'; return responseError('not_found', $notify); } return response()->json(['error' => 'Game not found']); } $validator = Validator::make($this->request->all(), $this->getValidationRules()); if ($validator->fails()) { if ($this->fromApi) { return responseError('validation_error', $validator->errors()->all()); } return response()->json(['errors' => $validator->errors()->all()]); } $fallback = $this->fallback(); if (isset($fallback['error']) && $fallback['error']) { if ($this->fromApi) { return responseError('fallback_error', $fallback['error']); } return response()->json($fallback); } $gameResult = $this->gameResult(); $invest = $this->invest($gameResult); $balance = $this->demoPlay ? $user->demo_balance : $user->balance; $res['game_log_id'] = $invest['game_log']?->id; $res['balance'] = showAmount($balance, currencyFormat: false); if ($this->resultShowOnStart) { $res['result'] = $gameResult['result']; } if ($this->extraResponseOnStart) { $res = array_merge($res, $this->extraResponseOnStart); } if ($this->fromApi) { $notify[] = $this->game->name . ' investment data'; return responseSuccess('investment_data', $notify, $res); } return response()->json($res); } public function complete() { if ($this->extraEndValidationRule) { $validator = Validator::make($this->request->all(), $this->extraEndValidationRule); if ($validator->fails()) { if ($this->fromApi) { return responseError('validation_error', $validator->errors()->all()); } return response()->json(['errors' => $validator->errors()->all()]); } } if (!$this->game) { if ($this->fromApi) { $notify[] = 'Game not found'; return responseError('not_found', $notify); } return response()->json(['error' => 'Game not found']); } $gameLog = GameLog::where('user_id', $this->user->id)->where('id', $this->request->game_log_id)->first(); if (!$gameLog) { if ($this->fromApi) { $notify[] = 'Game Logs not found'; return responseError('not_found', $notify); } return response()->json(['error' => 'Game Logs not found']); } if ($gameLog->status == Status::YES) { if ($this->fromApi) { $notify[] = 'Game Log already completed'; return responseError('game_completed', $notify); } return response()->json(['error' => 'Game Log already completed']); } $trx = getTrx(); if ($this->hasCustomCompleteLogic) { $customCompleteLogic = $this->customCompleteLogic($gameLog); if ($customCompleteLogic['should_return']) { if ($this->fromApi) { if (isset($customCompleteLogic['data']['error']) && $customCompleteLogic['data']['error']) { $notify[] = isset($customCompleteLogic['data']['error']) ? $customCompleteLogic['data']['error'] : 'Error Data'; return responseError('error', $notify); } $notify[] = isset($customCompleteLogic['data']['message']) ? $customCompleteLogic['data']['message'] : 'Success Data'; return responseSuccess('success_data', $notify, $customCompleteLogic['data']); } return response()->json($customCompleteLogic['data']); } } if ($gameLog->win_status == Status::WIN) { $winBon = $gameLog->invest * $this->game->win / 100; $amount = $winBon; $investBack = 0; if ($this->game->alias == 'mines') { $amount = $gameLog->win_amo; $winBon = $amount; } if ($this->game->invest_back == Status::YES) { $investBack = $gameLog->invest; if ($this->demoPlay) { $this->user->demo_balance += $gameLog->invest; } else { $this->user->balance += $gameLog->invest; } $this->user->save(); if (!$this->demoPlay) { $transaction = new Transaction(); $transaction->user_id = $this->user->id; $transaction->amount = $investBack; $transaction->charge = 0; $transaction->trx_type = '+'; $transaction->details = 'Invest Back For ' . $this->game->name; $transaction->remark = 'invest_back'; $transaction->trx = $trx; $transaction->post_balance = $this->user->balance; $transaction->save(); } } if ($this->demoPlay) { $this->user->demo_balance += $amount; } else { $this->user->balance += $amount; } $this->user->save(); $gameLog->win_amo = $amount; $gameLog->save(); if (!$this->demoPlay) { $transaction = new Transaction(); $transaction->user_id = $this->user->id; $transaction->amount = $winBon; $transaction->charge = 0; $transaction->trx_type = '+'; $transaction->details = 'Win bonus of ' . $this->game->name; $transaction->remark = 'Win_Bonus'; $transaction->trx = $trx; $transaction->post_balance = $this->user->balance; $transaction->save(); } $res['message'] = 'Yahoo! You Win!!!'; $res['type'] = 'success'; } else { $res['message'] = 'Oops! You Lost!!'; $res['type'] = 'danger'; } if ($this->extraResponseOnEnd) { $res = array_merge($res, $this->extraResponseOnEnd); } $balance = $this->demoPlay ? $this->user->demo_balance : $this->user->balance; $res['result'] = in_array($this->game->alias, ['keno']) ? json_decode($gameLog->result) : $gameLog->result; $res['user_choose'] = in_array($this->game->alias, ['keno']) ? json_decode($gameLog->user_select) : $gameLog->user_select; $res['win_status'] = $gameLog->win_status; $res['bal'] = showAmount($balance, currencyFormat: false); $gameLog->status = Status::GAME_FINISHED; $gameLog->save(); $this->checkAndGiveBonus($this->user->id, $this->game->id); if ($this->fromApi) { $notify[] = $this->game->name . ' result data'; return responseSuccess('result_data', $notify, $res); } if ($this->game->alias == 'pai_gow_poker') { $res['dealerCards'] = $customCompleteLogic['data']['dealer']; } return $res; } private function getValidationRules() { return array_merge($this->globalValidationRule, $this->extraValidationRule); } private function fallback() { $balance = $this->demoPlay ? $this->user->demo_balance : $this->user->balance; if ($this->request->invest > $balance) { return ['error' => 'Oops! You have no sufficient balance']; } $running = GameLog::where('status', 0)->where('user_id', $this->user->id)->where('game_id', $this->game->id)->first(); if ($running) { return ['error' => '1 game is in-complete. Please wait']; } if ($this->request->invest > $this->game->max_limit) { return ['error' => 'Please follow the maximum limit of invest']; } if ($this->request->invest < $this->game->min_limit) { return ['error' => 'Please follow the minimum limit of invest']; } return ['success']; } private function invest($gameResult) { $user = $this->user; if ($this->demoPlay) { $user->demo_balance -= $this->request->invest; } else { $user->balance -= $this->request->invest; } $user->save(); if (!$this->demoPlay) { $transaction = new Transaction(); $transaction->user_id = $user->id; $transaction->amount = $this->request->invest; $transaction->charge = 0; $transaction->trx_type = '-'; $transaction->details = 'Invest to ' . $this->game->name; $transaction->remark = 'invest'; $transaction->trx = getTrx(); $transaction->post_balance = $user->balance; $transaction->save(); } $gameLog = new GameLog(); $gameLog->user_id = $user->id ?? 0; $gameLog->game_id = $this->game->id; if ($this->demoPlay) { $gameLog->demo_play = Status::YES; } $gameLog->user_select = $this->userSelect; $gameLog->result = in_array($this->game->alias, ['number_slot', 'roulette', 'keno', 'poker', 'blackjack', 'pai_gow_poker']) ? json_encode($gameResult['result']) : ( $this->game->id == 4 ? decrypt($gameResult['result']) : $gameResult['result'] ); $gameLog->status = 0; $gameLog->win_status = isset($gameResult['win_status']) ? $gameResult['win_status'] : 0; $gameLog->invest = $this->request?->invest ?? 0; $gameLog->win_amo = isset($gameResult['win_amount']) ? $gameResult['win_amount'] : 0; $gameLog->mines = $this->request?->mines ?? 0; $gameLog->mine_available = $this->request?->mines ?? 0; $gameLog->save(); return ['game_log' => $gameLog]; } private function checkAndGiveBonus($userId, $gameId) { if (!gs('game_play')) { return; } $alreadyRewarded = GameplayBonusLog::where('user_id', $userId) ->where('game_id', $gameId) ->exists(); if ($alreadyRewarded) { return; } $user = User::find($userId); if (!$user) { return; } $requiredPlayCount = getAmount(gs('gameplay_number_for_bonus')); $bonusAmount = getAmount(gs('gameplay_bonus')); $playCount = $user->gameLogs()->where('game_id', $gameId)->where('demo_play', Status::NO)->count(); if ($playCount >= $requiredPlayCount) { $user->balance += $bonusAmount; $user->save(); $transaction = new Transaction(); $transaction->user_id = $user->id; $transaction->amount = $bonusAmount; $transaction->charge = 0; $transaction->trx_type = '+'; $transaction->details = 'Gameplay Bonus'; $transaction->remark = 'gameplay_bonus'; $transaction->trx = getTrx(); $transaction->post_balance = $user->balance; $transaction->save(); $bonusLog = new GameplayBonusLog(); $bonusLog->user_id = $userId; $bonusLog->game_id = $gameId; $bonusLog->amount = $bonusAmount; $bonusLog->save(); notify($user, 'GAMEPLAY_BONUS', [ 'amount' => showAmount($transaction->amount, currencyFormat: false), 'trx' => $transaction->trx, 'post_balance' => showAmount($user->balance, currencyFormat: false), ]); } } public function setRequest(Request $request) { $this->request = $request; } }