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
6declare(strict_types=1);
7
8namespace Tests\Models;
9
10use App\Models\Multiplayer\PlaylistItem;
11use App\Models\Multiplayer\Room;
12use App\Models\Season;
13use App\Models\SeasonRoom;
14use App\Models\User;
15use App\Models\UserSeasonScoreAggregate;
16use Tests\TestCase;
17
18class UserSeasonScoreAggregateTest extends TestCase
19{
20 private Season $season;
21 private User $user;
22
23 public function testAddMultipleScores(): void
24 {
25 $this->createRoomWithPlay('A', 10);
26
27 $userScore = UserSeasonScoreAggregate::where('user_id', $this->user->getKey())
28 ->where('season_id', $this->season->getKey())
29 ->first();
30
31 $this->assertSame(10.0, $userScore->total_score); // 10*1
32
33 $this->createRoomWithPlay('B', 15);
34
35 $userScore->refresh();
36 $this->assertSame(22.5, $userScore->total_score); // 15*1 + 10*0.75
37
38 $this->createRoomWithPlay('C', 25);
39
40 $userScore->refresh();
41 $this->assertSame(41.25, $userScore->total_score); // 25*1 + 15*0.75 + 10*0.5
42 }
43
44 public function testAddMultipleScoresWithChildrenRooms(): void
45 {
46 $this->createRoomWithPlay('A', 10);
47
48 $userScore = UserSeasonScoreAggregate::where('user_id', $this->user->getKey())
49 ->where('season_id', $this->season->getKey())
50 ->first();
51
52 $this->assertSame(10.0, $userScore->total_score); // 10*1
53
54 $this->createRoomWithPlay('A', 15);
55
56 $userScore->refresh();
57 $this->assertSame(15.0, $userScore->total_score); // 15*1
58
59 $this->createRoomWithPlay('B', 20);
60
61 $userScore->refresh();
62 $this->assertSame(31.25, $userScore->total_score); // 20*1 + 15*0.75
63
64 $this->createRoomWithPlay('B', 20);
65
66 $userScore->refresh();
67 $this->assertSame(31.25, $userScore->total_score); // 20*1 + 15*0.75
68
69 $this->createRoomWithPlay('C', 10);
70
71 $userScore->refresh();
72 $this->assertSame(36.25, $userScore->total_score); // 20*1 + 15*0.75 + 10*0.5
73
74 $this->createRoomWithPlay('C', 30);
75
76 $userScore->refresh();
77 $this->assertSame(52.5, $userScore->total_score); // 30*1 + 20*0.75 + 15*0.5
78 }
79
80 public function testAddHigherScoreInChildRoom(): void
81 {
82 $this->createRoomWithPlay('A', 10);
83
84 $userScore = UserSeasonScoreAggregate::where('user_id', $this->user->getKey())
85 ->where('season_id', $this->season->getKey())
86 ->first();
87
88 $this->assertSame(10.0, $userScore->total_score);
89
90 $this->createRoomWithPlay('A', 15);
91
92 $userScore->refresh();
93 $this->assertSame(15.0, $userScore->total_score);
94 }
95
96 public function testAddHigherScoreInParentRoom(): void
97 {
98 $this->createRoomWithPlay('A', 15);
99
100 $userScore = UserSeasonScoreAggregate::where('user_id', $this->user->getKey())
101 ->where('season_id', $this->season->getKey())
102 ->first();
103
104 $this->assertSame(15.0, $userScore->total_score);
105
106 $this->createRoomWithPlay('A', 10);
107
108 $userScore->refresh();
109 $this->assertSame(15.0, $userScore->total_score);
110 }
111
112 public function testAddSameScoreInChildAndParentRoom(): void
113 {
114 $this->createRoomWithPlay('A', 10);
115
116 $userScore = UserSeasonScoreAggregate::where('user_id', $this->user->getKey())
117 ->where('season_id', $this->season->getKey())
118 ->first();
119
120 $this->assertSame(10.0, $userScore->total_score);
121
122 $this->createRoomWithPlay('A', 10);
123
124 $userScore->refresh();
125 $this->assertSame(10.0, $userScore->total_score);
126 }
127
128 public function testAddScoreInChildRoomOnly(): void
129 {
130 $this->createRoom('A');
131 $this->createRoomWithPlay('A', 10);
132
133 $userScore = UserSeasonScoreAggregate::where('user_id', $this->user->getKey())
134 ->where('season_id', $this->season->getKey())
135 ->first();
136
137 $this->assertSame(10.0, $userScore->total_score);
138 }
139
140 public function testAddScoreInSecondRoomOnly(): void
141 {
142 $this->createRoom('A');
143 $this->createRoomWithPlay('B', 10);
144
145 $userScore = UserSeasonScoreAggregate::where('user_id', $this->user->getKey())
146 ->where('season_id', $this->season->getKey())
147 ->first();
148
149 $this->assertSame(10.0, $userScore->total_score);
150 }
151
152 protected function setUp(): void
153 {
154 parent::setUp();
155
156 $this->season = Season::factory()->create([
157 'score_factors' => [1, 0.75, 0.5],
158 ]);
159 $this->user = User::factory()->create();
160 }
161
162 private function createRoom(string $groupIndicator): Room
163 {
164 $room = Room::factory()->create([
165 'category' => 'spotlight',
166 ]);
167
168 SeasonRoom::factory()->create([
169 'group_indicator' => $groupIndicator,
170 'room_id' => $room,
171 'season_id' => $this->season,
172 ]);
173
174 return $room;
175 }
176
177 private function createRoomWithPlay(string $groupIndicator, float $totalScore): Room
178 {
179 $room = $this->createRoom($groupIndicator);
180
181 $playlistItem = PlaylistItem::factory()->create([
182 'owner_id' => $room->host,
183 'room_id' => $room,
184 ]);
185
186 static::roomAddPlay($this->user, $playlistItem, [
187 'passed' => true,
188 'total_score' => $totalScore,
189 ]);
190
191 return $room;
192 }
193}