ldc-gen-game-web/app/Http/Controllers/Bo/InstantWinController.php

154 lines
5.2 KiB
PHP

<?php
namespace App\Http\Controllers\Bo;
use App\Http\Controllers\Controller;
use App\Http\Resources\InstantWinResource;
use App\Models\InstantWin;
use App\Models\Prize;
use App\Models\Settings;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\DB;
class InstantWinController extends Controller
{
/**
* View Instant gagnants page
*
* @return \Illuminate\Contracts\View\View|\Illuminate\Contracts\View\Factory
*/
public function index()
{
// * Can generate only if there are none already generate and prizes on database
$canGenerate = InstantWin::count() ? false : (Prize::sum('quantity') ? true : false);
$instantWin = InstantWin::orderBy('appear_date')->get();
return view('bo.instant-win.index', [
'can_generate' => $canGenerate,
'instant_win' => new InstantWinResource($instantWin)
]);
}
/**
* Generate Instant wins
*
* @return \Illuminate\Http\JsonResponse
*/
public function instantWinGenerate(): JsonResponse
{
/** @var \App\Models\Settings $settings */
$settings = app(Settings::class);
/** @var \Illuminate\Support\Carbon $start_date */
$start_date = $settings->start_date;
/** @var \Illuminate\Support\Carbon $end_date */
$end_date = $settings->end_date;
$lots = Prize::orderBy('id')->get();
/** @var \Illuminate\Support\Collection $daterange all days of the game period */
$daterange = collect($start_date->range($end_date)->toArray());
/** @var \Illuminate\Support\Collection $dateGlobal all randomized instant wins */
$dateGlobal = collect();
/** @var \Illuminate\Support\Collection $lotsGlobal All randomized lots */
$lotsGlobal = collect();
// * Assign Lots on collection
foreach ($lots as $lot) {
for ($i = $lot->quantity; $i > 0; $i--) {
$lotsGlobal->push($lot);
}
}
$daysRunningGame = clone $daterange;
// * Create Instant wins on collection
for ($i = $lotsGlobal->count(); $i > 0; $i--) {
// * Get each day once then randomize
if ($daysRunningGame->count()) {
/** @var Carbon $dateTime */
$dateTime = $daysRunningGame->shift();
} else {
/** @var Carbon $dateTime */
$dateTime = $daterange->random();
}
// * If end of loop and there are less lots then days
if ($i === 1 and $lotsGlobal->count() < $daysRunningGame->count()) {
// * Make the last instant win on the last day
/** @var Carbon $dateTime */
$dateTime = $daterange->random();
}
$dateGlobal->push(Carbon::parse(sprintf(
'%s %s',
$dateTime->format('Y-m-d'),
$this->getRandomWiningHour()
)));
}//end for
// * Sort dates
$dateGlobal = $dateGlobal->sortBy(function (Carbon $date) {
return $date->getTimestamp();
});
// * Reserve big prize (the first should be ID 1) and last Instant win for the end
/** @var \App\Models\Prize $bigPrize */
$bigPrize = $lotsGlobal->shift();
/** @var Carbon $lastInstantWin */
$lastInstantWin = $dateGlobal->pop();
// * Shuffle Instant wins
// ! Initialize mt rand seed !!
\mt_srand();
$lotsGlobal = $lotsGlobal->shuffle(\mt_rand(0, 99999));
// * Shuffle Lots
// ! Initialize mt rand seed !!
\mt_srand();
$dateGlobal = $dateGlobal->shuffle(\mt_rand(0, 99999));
// ! Return empty if no prizes are available
if (!$bigPrize) {
return \response()->json();
}
$instantWinsLots = $dateGlobal->map(function (Carbon $instantWinDate) use ($lotsGlobal) {
return [
'date' => $instantWinDate,
'lot' => $lotsGlobal->shift()
];
});
// * Save Instant wins
DB::transaction(function () use ($instantWinsLots, $lastInstantWin, $bigPrize) {
$instantWinsLots->map(function (array $instantWinLot) {
$instantWin = new InstantWin();
$instantWin->appear_date = $instantWinLot['date'];
$instantWin->prize()->associate($instantWinLot['lot']);
$instantWin->saveOrFail();
});
// * Insert last Instant win (big prize)
$instantWin = new InstantWin();
$instantWin->appear_date = $lastInstantWin;
$instantWin->prize()->associate($bigPrize);
$instantWin->saveOrFail();
});
return \response()->json(new InstantWinResource(InstantWin::orderBy('appear_date')->get()));
}
/**
* Generate a random hour between 06:00 and 22:59
*
* @return string
*/
private function getRandomWiningHour(): string
{
// ! Initialize mt rand seed !!
\mt_srand();
return Carbon::parse('22:59')
->subMinutes(\mt_rand(0, (23 - 6) * 60 - 1))->format('H:i');
}
}