182 lines
6.4 KiB
PHP
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
|
|
}
|