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('appear_date')->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 */ $datesGlobal = collect(); /** * @var \Illuminate\Support\Collection * 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->appear_date = $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 $lotsGlobal * Liste de tous les lots à gagner * @param \Illuminate\Support\Collection $dateGlobal * @param integer $prizesDone * @return \Illuminate\Support\Collection * @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 $time * Un jour dans le temps. * @property \Illuminate\Support\Collection $lots * Liste des lots tombant ce jour. * @phpcs:disable PSR1.Classes.ClassDeclaration.MultipleClasses */ class WinDayCalendar extends \stdClass { // phpcs:enable }