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\Beatmap;
9
10/**
11 * @property Beatmap $beatmap
12 * @property int|null $beatmap_id
13 * @property \Carbon\Carbon|null $end_time
14 * @property \Illuminate\Database\Eloquent\Collection $events Event
15 * @property int $game_id
16 * @property LegacyMatch $legacyMatch
17 * @property int|null $match_id
18 * @property int|null $match_type
19 * @property mixed $mode
20 * @property int|null $mods
21 * @property int|null $play_mode
22 * @property \Illuminate\Database\Eloquent\Collection $scores Score
23 * @property int|null $scoring_type
24 * @property \Carbon\Carbon|null $start_time
25 * @property int|null $team_type
26 */
27class Game extends Model
28{
29 const SCORING_TYPES = [
30 'score' => 0,
31 'accuracy' => 1,
32 'combo' => 2,
33 'scorev2' => 3,
34 ];
35
36 const TEAM_TYPES = [
37 'head-to-head' => 0,
38 'tag-coop' => 1,
39 'team-vs' => 2,
40 'tag-team-vs' => 3,
41 ];
42
43 public static function scoringTypeStr(?int $scoringType): ?string
44 {
45 if ($scoringType === null) {
46 return null;
47 }
48
49 static $map;
50 $map ??= array_flip(static::SCORING_TYPES);
51
52 return $map[$scoringType] ?? null;
53 }
54
55 public static function teamTypeStr(?int $teamType): ?string
56 {
57 if ($teamType === null) {
58 return null;
59 }
60
61 static $map;
62 $map ??= array_flip(static::TEAM_TYPES);
63
64 return $map[$teamType] ?? null;
65 }
66
67 public $timestamps = false;
68
69 protected $casts = [
70 'end_time' => 'datetime',
71 'start_time' => 'datetime',
72 ];
73 protected $primaryKey = 'game_id';
74
75 public function scores()
76 {
77 return $this->hasMany(Score::class);
78 }
79
80 public function events()
81 {
82 return $this->hasMany(Event::class);
83 }
84
85 public function legacyMatch()
86 {
87 return $this->belongsTo(LegacyMatch::class, 'match_id');
88 }
89
90 public function beatmap()
91 {
92 return $this->belongsTo(Beatmap::class, 'beatmap_id');
93 }
94
95 public function getAttribute($key)
96 {
97 return match ($key) {
98 'beatmap_id',
99 'game_id',
100 'match_id',
101 'match_type' => $this->getRawAttribute($key),
102
103 'mode' => Beatmap::modeStr($this->play_mode),
104 'mods' => app('mods')->bitsetToIds($this->getRawAttribute($key)),
105 'scoring_type' => static::scoringTypeStr($this->getRawAttribute($key)),
106 'team_type' => static::teamTypeStr($this->getRawAttribute($key)),
107
108 'end_time',
109 'start_time' => $this->getTimeFast($key),
110
111 'end_time_json',
112 'start_time_json' => $this->getJsonTimeFast($key),
113
114 'play_mode' => $this->getRulesetId(),
115
116 'beatmap',
117 'events',
118 'legacyMatch',
119 'scores' => $this->getRelationValue($key),
120 };
121 }
122
123 private function getRulesetId(): int
124 {
125 $gameRulesetId = $this->getRawAttribute('play_mode') ?? Beatmap::MODES['osu'];
126 $beatmapRulesetId = $this->beatmap?->playmode;
127
128 // ruleset set at this model is incorrect when playing ruleset
129 // specific map with a different selected ruleset.
130 if ($beatmapRulesetId !== null && $beatmapRulesetId !== $gameRulesetId && $beatmapRulesetId !== Beatmap::MODES['osu']) {
131 return $beatmapRulesetId;
132 }
133
134 return $gameRulesetId;
135 }
136}