Added database structure and components

This commit is contained in:
2025-11-13 21:27:45 +00:00
parent 3f1c69c15b
commit 98a2ca4611
182 changed files with 3847 additions and 9 deletions
+214
View File
@@ -0,0 +1,214 @@
<?php
namespace Database\Seeders;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
use Carbon\Carbon;
use Illuminate\Container\Attributes\Database;
class GamesSeeder extends Seeder
{
private $ratioStandaloneToMatch = 15;
private function calculateRandomSeconds($filteredCollection)
{
$totalPlayers = $filteredCollection->count() + 1;
return (12 * 60 * 60) / $totalPlayers + rand(0, 2000);
}
private function nextGameDateTime(&$d, $filteredPlayers, $withinSameMatch = false) {
if ($withinSameMatch) {
$deltaSegundos = rand(300, 900);
} else {
$deltaSegundos = $this->calculateRandomSeconds($filteredPlayers);
}
$d->addSeconds($deltaSegundos);
}
public function run(): void
{
$this->command->info("Games seeder - Start");
$start = DB::table('users')->where('type', 'P')->min('created_at');
$allPlayers = DB::table('users')->where('type', 'P')->get();
$sortedPlayers = $allPlayers->sortBy('created_at')->values();
$d = new \Carbon\Carbon($start);
$d = $d->addDay();
$now = \Carbon\Carbon::now();
$this->command->info("Starting to create games");
$games = [];
$matches = [];
$i = 0;
$filteredPlayers = null;
$filteredPlayersIds = null;
$nextCreatedAt = null;
while ($d->lte($now)) {
$i++;
if (($filteredPlayers === null) || ($nextCreatedAt === null) ||
($d->gte($nextCreatedAt))
) {
$filteredPlayers = $allPlayers->filter(function ($value) use ($d) {
return $d->gt($value->created_at);
});
$nextCreatedAtPlayer = $sortedPlayers->first(function ($value) use ($d) {
return $d->lte($value->created_at);
});
$nextCreatedAt = $nextCreatedAtPlayer ? $nextCreatedAtPlayer->created_at : new \Carbon\Carbon('9999-12-31');
$filteredPlayersIds = $filteredPlayers->pluck('id')->toArray();
}
// Only creates games or matches when there are enough players
if ($filteredPlayersIds === null || empty($filteredPlayersIds) || count($filteredPlayersIds) <2) {
$this->nextGameDateTime($d, $filteredPlayers);
continue;
}
$userIdKeys = array_rand($filteredPlayersIds, 2);
$userIDPlayer1 = $filteredPlayersIds[$userIdKeys[0]];
$userIDPlayer2 = $filteredPlayersIds[$userIdKeys[1]];
if ($userIDPlayer1 == $userIDPlayer2) {
$this->nextGameDateTime($d, $filteredPlayers);
continue;
}
$match = null;
if (rand(1, $this->ratioStandaloneToMatch) === 1) {
$match = $this->newMatch($filteredPlayers, $userIDPlayer1, $userIDPlayer2, $d);
$playersMarks = [0, 0];
$playersPoints = [0, 0];
while($playersMarks[0] < 4 && $playersMarks[1] <4) {
$newGame = $this->newGame($filteredPlayers, $match, $userIDPlayer1, $userIDPlayer2, $d);
$games[] = $newGame;
$playersPoints[0] += $newGame['player1_points'];
$playersPoints[1] += $newGame['player2_points'];
if ($newGame['player1_points'] > $newGame['player2_points']) {
if ($newGame['player1_points'] >= 120) {
$playersMarks[0]+= 4;
} elseif ($newGame['player1_points'] >= 91) {
$playersMarks[0] += 2;
} else {
$playersMarks[0]++;
}
} elseif ($newGame['player2_points'] > $newGame['player1_points']) {
if ($newGame['player2_points'] >= 120) {
$playersMarks[1]+= 4;
} elseif ($newGame['player2_points'] >= 91) {
$playersMarks[1] += 2;
} else {
$playersMarks[1]++;
}
}
}
$this->updateMatchWinner($match, $playersMarks[0], $playersMarks[1], $playersPoints[0], $playersPoints[1], $d);
$matches[] = $match;
} else {
$newGame = $this->newGame($filteredPlayers, $match, $userIDPlayer1, $userIDPlayer2, $d);
$games[] = $newGame;
}
if ($i >= DatabaseSeeder::$dbInsertBlockSize) {
if (!empty($matches)) {
DB::table('matches')->insert($matches);
$this->command->info("Saved " . count($matches) . " matches at date " . $d->format('Y-m-d H:i:s'));
}
if (!empty($games)) {
DB::table('games')->insert($games);
$this->command->info("Saved " . count($games) . " games at date " . $d->format('Y-m-d H:i:s'));
}
$i = 0;
$games = [];
$matches = [];
}
//$this->nextGameDateTime($d, $filteredPlayers);
}
if (!empty($matches)) {
DB::table('matches')->insert($matches);
$this->command->info("Saved " . count($matches) . " matches at date " . $d->format('Y-m-d H:i:s'));
}
if (!empty($games)) {
DB::table('games')->insert($games);
$this->command->info("Saved " . count($games) . " games at date " . $d->format('Y-m-d H:i:s'));
}
$this->command->info("Games seeder - End");
}
private $matchID = 0;
private function newMatch($filteredPlayers,$user1, $user2, $d)
{
$this->matchID++;
$this->nextGameDateTime($d, $filteredPlayers);
return [
'id' => $this->matchID,
'type' => random_int(1,2) == 1 ? '3' : '9',
'player1_user_id' => $user1,
'player2_user_id' => $user2,
'winner_user_id' => null,
'loser_user_id' => null,
'status' => 'Ended',
'stake' => random_int(1,4) > 1 ? 3 : random_int(4,100),
'began_at' => $d->copy(),
'ended_at' => null,
'total_time' => null,
'player1_marks' => null,
'player2_marks' => null,
'player1_points' => null,
'player2_points' => null,
'custom' => null
];
}
private function updateMatchWinner(&$match, $player1Marks, $player2Marks, $totalPlayers1, $totalPlayers2, $d)
{
$match['player1_marks'] = $player1Marks;
$match['player2_marks'] = $player2Marks;
$match['player1_points'] = $totalPlayers1;
$match['player2_points'] = $totalPlayers2;
$match['ended_at'] = $d->copy();
$match['total_time'] = $match['began_at']->diffInSeconds($match['ended_at']);
$match['winner_user_id'] = $player1Marks > $player2Marks ? $match['player1_user_id'] : ($player2Marks > $player1Marks ? $match['player2_user_id'] : null);
$match['loser_user_id'] = $player1Marks > $player2Marks ? $match['player2_user_id'] : ($player2Marks > $player1Marks ? $match['player1_user_id'] : null);
}
private $gameID = 0;
private function newGame($filteredPlayers, $match, $user1, $user2, $d)
{
$this->gameID++;
$this->nextGameDateTime($d, $filteredPlayers, $match != null);
$begin_d = $d->copy();
$pointsUser1 = 60;
$pointsUser2 = 60;
// if random == 1 it is a draw
if (random_int(1,30) > 1) {
$pointsUser1 = rand(0, 120);
$pointsUser2 = 120 - $pointsUser1;
}
$duration = random_int(200, 900);
$d->addSeconds($duration);
return [
'id' => $this->gameID,
'type' => $match ? $match['type'] : (random_int(1, 2) == 1 ? '3' : '9'),
'match_id' => $match ? $match['id'] : null,
'player1_user_id' => $user1,
'player2_user_id' => $user2,
'is_draw' => $pointsUser1 == $pointsUser2,
'winner_user_id' => $pointsUser1 > $pointsUser2 ? $user1 : ($pointsUser2 > $pointsUser1 ? $user2 : null),
'loser_user_id' => $pointsUser1 < $pointsUser2 ? $user1 : ($pointsUser2 < $pointsUser1 ? $user2 : null),
'status' => 'Ended',
'began_at' => $begin_d,
'ended_at' => $d->copy(),
'total_time' => $duration,
'player1_points' => $pointsUser1,
'player2_points' => $pointsUser2,
'custom' => null
];
}
}