ldc-gen-game-web/app/Http/Controllers/Bo/InstantWinController.php
noah.lancien 218a3a7891 phpstan
2024-01-31 09:03:18 +00:00

182 lines
6.4 KiB
PHP

<?php
namespace App\Http\Controllers\Bo;
use App\Http\Controllers\Controller;
use App\Models\InstantWin;
use App\Models\Prize;
use App\Models\Settings;
use Carbon\CarbonInterval;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;
class InstantWinController extends Controller
{
/**
* Create the controller instance.
*/
public function __construct()
{
$this->authorizeResource(InstantWin::class);
}
/**
* Display a listing of the resource.
*
* @return \Illuminate\Contracts\View\View
*/
public function index(): \Illuminate\Contracts\View\View
{
$instantWinModelList = InstantWin::query()->orderBy('available_at')->get();
return view('back::pages.instant-win.index', [
'instantWinModelList' => $instantWinModelList
]);
}
/**
* Returns generated instant win.
*
* @return \Illuminate\Http\JsonResponse
*/
public function generate(): JsonResponse
{
$this->authorize('generate', InstantWin::class);
return DB::transaction(function () {
/**
* À partir de quelle heure on peut gagner
* ! Seul l'heure sera prize en compte
*/
$day_start = now()->setTime(6, 0);
/**
* Jusqu'à quelle heure on peut gagner
* ! Seul l'heure sera prize en compte
*/
$day_end = now()->setTime(22, 29);
/** @var \App\Models\Settings */
$settings = app(Settings::class);
$prizeModelList = Prize::all();
/** @var \Illuminate\Support\Collection<array-key,\App\Http\Controllers\Bo\WinDayCalendar> */
$datesGlobal = collect();
/**
* @var \Illuminate\Support\Collection<array-key,\App\Http\Controllers\Bo\WinTimeElement>
* Liste de tous les lots à gagner
*/
$lotsGlobal = collect();
// * Seed srand !
\mt_srand(time());
// * Init prize list
$prizeModelList->each(function (Prize $prize) use ($lotsGlobal, $day_start, $day_end) {
for ($i = 0; $i < $prize->quantity; $i++) {
$el = new WinTimeElement();
$el->prize = $prize;
$el->time = now()->setTime(
mt_rand($day_start->hour, $day_end->hour),
mt_rand($day_start->minute, $day_end->minute)
);
$lotsGlobal->push($el);
}
});
$lotsGlobal->shuffle(time());
// * Init days calendar
foreach ($settings->start_date->toPeriod($settings->end_date, CarbonInterval::make('1day')) as $date) {
$el = new WinDayCalendar();
$el->lots = collect();
$el->time = $date->setTime(0, 0);
$datesGlobal->push($el);
}
// * Save Instant wins
$this->generateArray($lotsGlobal, $datesGlobal, 0)->each(function (WinDayCalendar $winDayCalendar) {
$winDayCalendar->lots->each(function (WinTimeElement $winTimeElement) {
$instantWin = new InstantWin();
$instantWin->available_at = $winTimeElement->time;
$instantWin->prize()->associate($winTimeElement->prize);
$instantWin->saveOrFail();
});
});
// * Output instant wins to ajax response
return response()->json(InstantWin::all());
});
}
/**
* Generate instant win.
*
* Même algo que celui implémenté par Romain.
*
* @param \Illuminate\Support\Collection<array-key,\App\Http\Controllers\Bo\WinTimeElement> $lotsGlobal
* Liste de tous les lots à gagner
* @param \Illuminate\Support\Collection<array-key,\App\Http\Controllers\Bo\WinDayCalendar> $dateGlobal
* @param integer $prizesDone
* @return \Illuminate\Support\Collection<array-key,\App\Http\Controllers\Bo\WinDayCalendar>
* @phpcs:disable Squiz.Commenting.FunctionComment.IncorrectTypeHint
*/
private function generateArray(Collection $lotsGlobal, Collection $dateGlobal, int $prizesDone): Collection
{
// phpcs:enable
/** @var array-key Un jour sélectionné aléatoire. */
$rKey = $dateGlobal->keys()->random(1)->firstOrFail();
// ? À-t-on déjà assigné un lot par jour (au moins) ?
// ? Le jour aléatoire sélectionné à déja un lot ?
if ($prizesDone < $dateGlobal->count() and $dateGlobal->get($rKey)->lots->count() > 0) {
return $this->generateArray($lotsGlobal, $dateGlobal, $prizesDone);
}
// * Insert next prize on a randowm day
$dateGlobal->get($rKey)->lots->push($lotsGlobal->get($prizesDone++));
// ? On a distribué assez de lots ?
if ($prizesDone < $lotsGlobal->count()) {
return $this->generateArray($lotsGlobal, $dateGlobal, $prizesDone);
}
// * Tri par heure et assignation du jour correct.
$dateGlobal->each(function (WinDayCalendar $date) {
$date->lots = $date->lots->sort(fn (WinTimeElement $a, WinTimeElement $b) =>
$a->time->timestamp - $b->time->timestamp)
->map(function (WinTimeElement $time) use ($date) {
$time->time->setDate(
$date->time->year,
$date->time->month,
$date->time->day
);
return $time;
});
});
return $dateGlobal;
}
}
/**
* @property \App\Models\Prize $prize Le lot à gagner.
* @property \Carbon\Carbon $time Une heure aléatoire.
* @phpcs:disable PSR1.Classes.ClassDeclaration.MultipleClasses
*/
class WinTimeElement extends \stdClass
{
// phpcs:enable
}
/**
* @property \Carbon\Carbon|\Carbon\CarbonInterface $time
* Un jour dans le temps.
* @property \Illuminate\Support\Collection<array-key,\App\Http\Controllers\Bo\WinTimeElement> $lots
* Liste des lots tombant ce jour.
* @phpcs:disable PSR1.Classes.ClassDeclaration.MultipleClasses
*/
class WinDayCalendar extends \stdClass
{
// phpcs:enable
}