init commit
This commit is contained in:
commit
c9d982669a
461 changed files with 30317 additions and 0 deletions
66
app/Models/BreakPeriod.php
Normal file
66
app/Models/BreakPeriod.php
Normal file
|
@ -0,0 +1,66 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
||||
|
||||
class BreakPeriod extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*
|
||||
* @var array<int, string>
|
||||
*/
|
||||
protected $fillable = [
|
||||
'competition_id',
|
||||
'field_id',
|
||||
'name',
|
||||
'description',
|
||||
'start_time',
|
||||
'end_time',
|
||||
'type',
|
||||
'status',
|
||||
'round',
|
||||
'match_slot',
|
||||
];
|
||||
|
||||
/**
|
||||
* The attributes that should be cast.
|
||||
*
|
||||
* @var array<string, string>
|
||||
*/
|
||||
protected $casts = [
|
||||
'start_time' => 'datetime',
|
||||
'end_time' => 'datetime',
|
||||
];
|
||||
|
||||
/**
|
||||
* Get the competition that this break period belongs to.
|
||||
*/
|
||||
public function competition(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Competition::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the field that this break period belongs to.
|
||||
*/
|
||||
public function field(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Field::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the teams that are on break during this period.
|
||||
*/
|
||||
public function teams(): BelongsToMany
|
||||
{
|
||||
return $this->belongsToMany(Team::class)
|
||||
->withTimestamps();
|
||||
}
|
||||
}
|
90
app/Models/Competition.php
Normal file
90
app/Models/Competition.php
Normal file
|
@ -0,0 +1,90 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
|
||||
class Competition extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*
|
||||
* @var array<int, string>
|
||||
*/
|
||||
protected $fillable = [
|
||||
'name',
|
||||
'description',
|
||||
'start_date',
|
||||
'end_date',
|
||||
'status',
|
||||
'location',
|
||||
'max_teams',
|
||||
'current_scheduling_mode_id',
|
||||
];
|
||||
|
||||
/**
|
||||
* The attributes that should be cast.
|
||||
*
|
||||
* @var array<string, string>
|
||||
*/
|
||||
protected $casts = [
|
||||
'start_date' => 'date',
|
||||
'end_date' => 'date',
|
||||
];
|
||||
|
||||
/**
|
||||
* Get the teams participating in the competition.
|
||||
*/
|
||||
public function teams(): BelongsToMany
|
||||
{
|
||||
return $this->belongsToMany(Team::class)
|
||||
->withTimestamps()
|
||||
->withPivot('status');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the scheduling modes available for this competition.
|
||||
*/
|
||||
public function schedulingModes(): HasMany
|
||||
{
|
||||
return $this->hasMany(SchedulingMode::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current scheduling mode for this competition.
|
||||
*/
|
||||
public function currentSchedulingMode()
|
||||
{
|
||||
return $this->belongsTo(SchedulingMode::class, 'current_scheduling_mode_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the matches for this competition.
|
||||
*/
|
||||
public function matches(): HasMany
|
||||
{
|
||||
return $this->hasMany(MatchGame::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the break periods for this competition.
|
||||
*/
|
||||
public function breakPeriods(): HasMany
|
||||
{
|
||||
return $this->hasMany(BreakPeriod::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the fields used in this competition.
|
||||
*/
|
||||
public function fields(): BelongsToMany
|
||||
{
|
||||
return $this->belongsToMany(Field::class)
|
||||
->withTimestamps();
|
||||
}
|
||||
}
|
64
app/Models/Field.php
Normal file
64
app/Models/Field.php
Normal file
|
@ -0,0 +1,64 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
|
||||
class Field extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*
|
||||
* @var array<int, string>
|
||||
*/
|
||||
protected $fillable = [
|
||||
'name',
|
||||
'location',
|
||||
'description',
|
||||
'status',
|
||||
'capacity',
|
||||
'surface_type',
|
||||
'indoor',
|
||||
'dimensions',
|
||||
];
|
||||
|
||||
/**
|
||||
* The attributes that should be cast.
|
||||
*
|
||||
* @var array<string, string>
|
||||
*/
|
||||
protected $casts = [
|
||||
'indoor' => 'boolean',
|
||||
'dimensions' => 'array',
|
||||
];
|
||||
|
||||
/**
|
||||
* Get the competitions that use this field.
|
||||
*/
|
||||
public function competitions(): BelongsToMany
|
||||
{
|
||||
return $this->belongsToMany(Competition::class)
|
||||
->withTimestamps();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the matches scheduled on this field.
|
||||
*/
|
||||
public function matches(): HasMany
|
||||
{
|
||||
return $this->hasMany(MatchGame::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the break periods scheduled on this field.
|
||||
*/
|
||||
public function breakPeriods(): HasMany
|
||||
{
|
||||
return $this->hasMany(BreakPeriod::class);
|
||||
}
|
||||
}
|
105
app/Models/MatchGame.php
Normal file
105
app/Models/MatchGame.php
Normal file
|
@ -0,0 +1,105 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
|
||||
class MatchGame extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
/**
|
||||
* The table associated with the model.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $table = 'matches';
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*
|
||||
* @var array<int, string>
|
||||
*/
|
||||
protected $fillable = [
|
||||
'competition_id',
|
||||
'scheduling_mode_id',
|
||||
'home_team_id',
|
||||
'away_team_id',
|
||||
'field_id',
|
||||
'start_time',
|
||||
'end_time',
|
||||
'home_team_score',
|
||||
'away_team_score',
|
||||
'status',
|
||||
'round',
|
||||
'group',
|
||||
'match_number',
|
||||
];
|
||||
|
||||
/**
|
||||
* The attributes that should be cast.
|
||||
*
|
||||
* @var array<string, string>
|
||||
*/
|
||||
protected $casts = [
|
||||
'start_time' => 'datetime',
|
||||
'end_time' => 'datetime',
|
||||
'home_team_score' => 'integer',
|
||||
'away_team_score' => 'integer',
|
||||
];
|
||||
|
||||
/**
|
||||
* Get the competition that the match belongs to.
|
||||
*/
|
||||
public function competition(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Competition::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the scheduling mode that this match is part of.
|
||||
*/
|
||||
public function schedulingMode(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(SchedulingMode::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the home team.
|
||||
*/
|
||||
public function homeTeam(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Team::class, 'home_team_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the away team.
|
||||
*/
|
||||
public function awayTeam(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Team::class, 'away_team_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the field where the match is played.
|
||||
*/
|
||||
public function field(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Field::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if this match is during a break period.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasBankPeriod()
|
||||
{
|
||||
return BreakPeriod::where('competition_id', $this->competition_id)
|
||||
->where('start_time', '<=', $this->start_time)
|
||||
->where('end_time', '>=', $this->end_time)
|
||||
->exists();
|
||||
}
|
||||
}
|
42
app/Models/Permission.php
Normal file
42
app/Models/Permission.php
Normal file
|
@ -0,0 +1,42 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class Permission extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $fillable = [
|
||||
'name',
|
||||
'display_name',
|
||||
'description',
|
||||
'is_wildcard'
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'is_wildcard' => 'boolean'
|
||||
];
|
||||
|
||||
public function roles()
|
||||
{
|
||||
return $this->belongsToMany(Role::class)->withpivot('granted')->withTimestamps();
|
||||
}
|
||||
|
||||
public function users()
|
||||
{
|
||||
return $this->belongsToMany(User::class)->withPivot('granted')->withTimestamps();
|
||||
}
|
||||
|
||||
public function matches($permission)
|
||||
{
|
||||
if (!$this->is_wildcard) {
|
||||
return $this->name === $permission;
|
||||
}
|
||||
|
||||
$pattern = str_replace('*', '.*', $this->name);
|
||||
return preg_match('/^' . $pattern . '$/', $permission);
|
||||
}
|
||||
}
|
47
app/Models/Role.php
Normal file
47
app/Models/Role.php
Normal file
|
@ -0,0 +1,47 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class Role extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $fillable = [
|
||||
'name',
|
||||
'display_name',
|
||||
'description'
|
||||
];
|
||||
|
||||
public function permissions()
|
||||
{
|
||||
return $this->belongsToMany(Permission::class)->withPivot('granted')->withTimestamps();
|
||||
}
|
||||
|
||||
public function users()
|
||||
{
|
||||
return $this->belongsToMany(User::class)->withTimestamps();
|
||||
}
|
||||
|
||||
public function hasPermission($permission)
|
||||
{
|
||||
return $this->permissions->where('pivot.granted', true)->contains('name', $permission) ||
|
||||
$this->hasWildcardPermission($permission);
|
||||
}
|
||||
|
||||
private function hasWildcardPermission($permission)
|
||||
{
|
||||
$wildcardPermissions = $this->permissions->where('is_wildcard', true)->where('pivot.granted', true);
|
||||
|
||||
foreach ($wildcardPermissions as $wildcardPermission) {
|
||||
$pattern = str_replace('*', '.*', $wildcardPermission->name);
|
||||
if (preg_match('/^' . $pattern . '$/', $permission)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
128
app/Models/SchedulingMode.php
Normal file
128
app/Models/SchedulingMode.php
Normal file
|
@ -0,0 +1,128 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
|
||||
class SchedulingMode extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*
|
||||
* @var array<int, string>
|
||||
*/
|
||||
protected $fillable = [
|
||||
'competition_id',
|
||||
'name',
|
||||
'description',
|
||||
'algorithm',
|
||||
'config',
|
||||
'sequence_order',
|
||||
'status',
|
||||
];
|
||||
|
||||
/**
|
||||
* The attributes that should be cast.
|
||||
*
|
||||
* @var array<string, string>
|
||||
*/
|
||||
protected $casts = [
|
||||
'config' => 'array',
|
||||
];
|
||||
|
||||
/**
|
||||
* Get the competition that this scheduling mode belongs to.
|
||||
*/
|
||||
public function competition(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Competition::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the matches associated with this scheduling mode.
|
||||
*/
|
||||
public function matches(): HasMany
|
||||
{
|
||||
return $this->hasMany(MatchGame::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get competitions that are currently using this scheduling mode.
|
||||
*/
|
||||
public function activeCompetitions(): HasMany
|
||||
{
|
||||
return $this->hasMany(Competition::class, 'current_scheduling_mode_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if this is the current active scheduling mode for its competition.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isActive(): bool
|
||||
{
|
||||
return $this->competition->current_scheduling_mode_id === $this->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate match schedule based on the algorithm defined.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function generateSchedule(): array
|
||||
{
|
||||
// This would contain the logic to delegate to different scheduling algorithms
|
||||
// based on the 'algorithm' field
|
||||
switch ($this->algorithm) {
|
||||
case 'round_robin':
|
||||
return $this->generateRoundRobinSchedule();
|
||||
|
||||
case 'knockout':
|
||||
return $this->generateKnockoutSchedule();
|
||||
|
||||
case 'group_stage':
|
||||
return $this->generateGroupStageSchedule();
|
||||
|
||||
default:
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Example implementation for round-robin scheduling.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function generateRoundRobinSchedule(): array
|
||||
{
|
||||
// Implementation would go here
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Example implementation for knockout scheduling.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function generateKnockoutSchedule(): array
|
||||
{
|
||||
// Implementation would go here
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Example implementation for group stage scheduling.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function generateGroupStageSchedule(): array
|
||||
{
|
||||
// Implementation would go here
|
||||
return [];
|
||||
}
|
||||
}
|
70
app/Models/Team.php
Normal file
70
app/Models/Team.php
Normal file
|
@ -0,0 +1,70 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
|
||||
class Team extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*
|
||||
* @var array<int, string>
|
||||
*/
|
||||
protected $fillable = [
|
||||
'name',
|
||||
'logo',
|
||||
'nb_players',
|
||||
'contact_email',
|
||||
'contact_phone',
|
||||
'status',
|
||||
];
|
||||
|
||||
/**
|
||||
* Get the competitions this team is participating in.
|
||||
*/
|
||||
public function competitions(): BelongsToMany
|
||||
{
|
||||
return $this->belongsToMany(Competition::class)
|
||||
->withTimestamps()
|
||||
->withPivot('status');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the matches where this team is the home team.
|
||||
*/
|
||||
public function homeMatches(): HasMany
|
||||
{
|
||||
return $this->hasMany(MatchGame::class, 'home_team_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the matches where this team is the away team.
|
||||
*/
|
||||
public function awayMatches(): HasMany
|
||||
{
|
||||
return $this->hasMany(MatchGame::class, 'away_team_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all matches for this team (both home and away).
|
||||
*/
|
||||
public function matches()
|
||||
{
|
||||
return $this->homeMatches->merge($this->awayMatches);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the break periods assigned to this team.
|
||||
*/
|
||||
public function breakPeriods(): BelongsToMany
|
||||
{
|
||||
return $this->belongsToMany(BreakPeriod::class)
|
||||
->withTimestamps();
|
||||
}
|
||||
}
|
158
app/Models/User.php
Normal file
158
app/Models/User.php
Normal file
|
@ -0,0 +1,158 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Concerns\HasUuids;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Foundation\Auth\User as Authenticatable;
|
||||
use Illuminate\Notifications\Notifiable;
|
||||
|
||||
class User extends Authenticatable
|
||||
{
|
||||
/** @use HasFactory<\Database\Factories\UserFactory> */
|
||||
use HasFactory, Notifiable, HasUuids;
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*
|
||||
* @var list<string>
|
||||
*/
|
||||
protected $fillable = [
|
||||
'name',
|
||||
'email',
|
||||
'avatar',
|
||||
'oidc_id',
|
||||
];
|
||||
|
||||
/**
|
||||
* The attributes that should be hidden for serialization.
|
||||
*
|
||||
* @var list<string>
|
||||
*/
|
||||
protected $hidden = [
|
||||
'password',
|
||||
'remember_token',
|
||||
];
|
||||
|
||||
/**
|
||||
* Get the attributes that should be cast.
|
||||
*
|
||||
* @return array<string, string>
|
||||
*/
|
||||
protected function casts(): array
|
||||
{
|
||||
return [
|
||||
'email_verified_at' => 'datetime',
|
||||
'password' => 'hashed',
|
||||
];
|
||||
}
|
||||
|
||||
public function roles()
|
||||
{
|
||||
return $this->belongsToMany(Role::class)->withTimestamps();
|
||||
}
|
||||
|
||||
public function permissions()
|
||||
{
|
||||
return $this->belongsToMany(Permission::class)->withPivot('granted')->withTimestamps();
|
||||
}
|
||||
|
||||
public function hasRole($role)
|
||||
{
|
||||
if (is_string($role)) {
|
||||
return $this->roles->contains('name', $role);
|
||||
}
|
||||
|
||||
return $this->roles->contains($role);
|
||||
}
|
||||
|
||||
public function hasAnyRole($roles)
|
||||
{
|
||||
if (is_array($roles)) {
|
||||
return $this->roles->whereIn('name', $roles)->isNotEmpty();
|
||||
}
|
||||
|
||||
return $this->hasRole($roles);
|
||||
}
|
||||
|
||||
public function hasPermission($permission)
|
||||
{
|
||||
// Check direct permissions
|
||||
if ($this->hasDirectPermission($permission)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check role-based permissions
|
||||
return $this->hasRolePermission($permission);
|
||||
}
|
||||
|
||||
private function hasDirectPermission($permission)
|
||||
{
|
||||
// Check exact match with granted
|
||||
if ($this->permissions->where('pivot.granted', true)->contains('name', $permission)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check wildcard permissions with granted
|
||||
$wildcardPermissions = $this->permissions->where('is_wildcard', true)->where('pivot.granted', true);
|
||||
|
||||
foreach ($wildcardPermissions as $wildcardPermission) {
|
||||
if ($wildcardPermission->matches($permission)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private function hasRolePermission($permission)
|
||||
{
|
||||
foreach ($this->roles as $role) {
|
||||
if ($role->hasPermission($permission)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function assignRole($role)
|
||||
{
|
||||
if (is_string($role)) {
|
||||
$role = Role::where('name', $role)->firstOrFail();
|
||||
}
|
||||
|
||||
$this->roles()->syncWithoutDetaching([$role->id]);
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function removeRole($role)
|
||||
{
|
||||
if (is_string($role)) {
|
||||
$role = Role::where('name', $role)->firstOrFail();
|
||||
}
|
||||
|
||||
$this->roles()->detach($role->id);
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function givePermission($permission)
|
||||
{
|
||||
if (is_string($permission)) {
|
||||
$permission = Permission::where('name', $permission)->firstOrFail();
|
||||
}
|
||||
|
||||
$this->permissions()->syncWithoutDetaching([$permission->id => ['granted' => true]]);
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function revokePermission($permission)
|
||||
{
|
||||
if (is_string($permission)) {
|
||||
$permission = Permission::where('name', $permission)->firstOrFail();
|
||||
}
|
||||
|
||||
$this->permissions()->updateExistingPivot($permission->id, ['granted' => false]);
|
||||
return $this;
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue