1<?php
2
3// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the GNU Affero General Public License v3.0.
4// See the LICENCE file in the repository root for full licence text.
5
6namespace App\Models\LegacyMatch;
7
8use App\Models\Traits\WithDbCursorHelper;
9use App\Models\User;
10use Cache;
11
12/**
13 * @property \Carbon\Carbon|null $end_time
14 * @property \Illuminate\Database\Eloquent\Collection $events Event
15 * @property \Illuminate\Database\Eloquent\Collection $games Game
16 * @property mixed $keep_forever
17 * @property int $match_id
18 * @property string $name
19 * @property mixed $private
20 * @property \Carbon\Carbon|null $start_time
21 */
22class LegacyMatch extends Model
23{
24 use WithDbCursorHelper;
25
26 const SORTS = [
27 'id_asc' => [
28 ['column' => 'match_id', 'order' => 'ASC'],
29 ],
30 'id_desc' => [
31 ['column' => 'match_id', 'order' => 'DESC'],
32 ],
33 ];
34
35 const DEFAULT_SORT = 'id_desc';
36
37 public $timestamps = false;
38
39 protected $casts = [
40 'keep_forever' => 'boolean',
41 'start_time' => 'datetime',
42 'end_time' => 'datetime',
43 ];
44 protected $primaryKey = 'match_id';
45 protected $table = 'matches';
46
47 public function games()
48 {
49 return $this->hasMany(Game::class);
50 }
51
52 public function events()
53 {
54 return $this->hasMany(Event::class);
55 }
56
57 public function currentGame()
58 {
59 $game = $this->games()->last();
60
61 if ($game !== null && $game->end_time === null) {
62 return $game;
63 }
64 }
65
66 public function hadPlayer(User $user)
67 {
68 return Cache::remember("multiplayer_participation_{$this->match_id}_{$user->user_id}", 60, function () use ($user) {
69 return $this->events()->where('user_id', $user->user_id)->whereIn('text', ['CREATE', 'JOIN'])->exists();
70 });
71 }
72
73 public function isTournamentMatch()
74 {
75 // keep_forever is being re-purposed to mark matches as 'tournament matches' (which will allow for public-read of chat and what-not)
76 return $this->keep_forever;
77 }
78
79 public function currentPlayers()
80 {
81 $players = [];
82 if (!$this->end_time) { // match hasn't ended, i.e. ongoing match
83 $join_events = $this->events()->whereIn('text', ['JOIN', 'PART'])->orderBy('event_id', 'asc')->get();
84 foreach ($join_events as $event) {
85 if ($event->text === 'JOIN') {
86 array_push($players, $event->user_id);
87 } else {
88 array_splice($players, array_search($event->user_id, $players, true), 1);
89 }
90 }
91 }
92
93 return $players;
94 }
95}