diff --git a/app/Models/SeasonRoom.php b/app/Models/SeasonRoom.php index 86397032a1d..a5bbfc281c3 100644 --- a/app/Models/SeasonRoom.php +++ b/app/Models/SeasonRoom.php @@ -7,6 +7,7 @@ namespace App\Models; +use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; /** @@ -16,5 +17,7 @@ */ class SeasonRoom extends Model { + use HasFactory; + public $timestamps = false; } diff --git a/app/Models/SeasonScoreFactor.php b/app/Models/SeasonScoreFactor.php index 0e658b5aed3..aff70c8fa59 100644 --- a/app/Models/SeasonScoreFactor.php +++ b/app/Models/SeasonScoreFactor.php @@ -5,6 +5,8 @@ namespace App\Models; +use Illuminate\Database\Eloquent\Factories\HasFactory; + /** * @property int $id * @property float $factor @@ -12,5 +14,7 @@ */ class SeasonScoreFactor extends Model { + use HasFactory; + public $timestamps = false; } diff --git a/database/factories/SeasonRoomFactory.php b/database/factories/SeasonRoomFactory.php new file mode 100644 index 00000000000..3492702f4f3 --- /dev/null +++ b/database/factories/SeasonRoomFactory.php @@ -0,0 +1,21 @@ +. Licensed under the GNU Affero General Public License v3.0. +// See the LICENCE file in the repository root for full licence text. + +declare(strict_types=1); + +namespace Database\Factories; + +use App\Models\SeasonRoom; + +class SeasonRoomFactory extends Factory +{ + protected $model = SeasonRoom::class; + + public function definition(): array + { + // pivot table... + return []; + } +} diff --git a/database/factories/SeasonScoreFactorFactory.php b/database/factories/SeasonScoreFactorFactory.php new file mode 100644 index 00000000000..1df687bdf53 --- /dev/null +++ b/database/factories/SeasonScoreFactorFactory.php @@ -0,0 +1,22 @@ +. Licensed under the GNU Affero General Public License v3.0. +// See the LICENCE file in the repository root for full licence text. + +declare(strict_types=1); + +namespace Database\Factories; + +use App\Models\SeasonScoreFactor; + +class SeasonScoreFactorFactory extends Factory +{ + protected $model = SeasonScoreFactor::class; + + public function definition(): array + { + return [ + 'factor' => 1, + ]; + } +} diff --git a/tests/Models/UserSeasonScoreTest.php b/tests/Models/UserSeasonScoreTest.php new file mode 100644 index 00000000000..11e5f9d9eab --- /dev/null +++ b/tests/Models/UserSeasonScoreTest.php @@ -0,0 +1,202 @@ +. Licensed under the GNU Affero General Public License v3.0. +// See the LICENCE file in the repository root for full licence text. + +declare(strict_types=1); + +namespace Tests\Models; + +use App\Models\Multiplayer\PlaylistItem; +use App\Models\Multiplayer\Room; +use App\Models\Season; +use App\Models\SeasonRoom; +use App\Models\SeasonScoreFactor; +use App\Models\User; +use App\Models\UserSeasonScore; +use Tests\TestCase; + +class UserSeasonScoreTest extends TestCase +{ + private Season $season; + private User $user; + + public function testAddMultipleScores(): void + { + foreach ([1, 0.75, 0.5] as $factor) { + SeasonScoreFactor::factory()->create([ + 'factor' => $factor, + 'season_id' => $this->season, + ]); + } + + $this->createRoomWithPlay(10); + + $userScore = UserSeasonScore::where('user_id', $this->user->getKey()) + ->where('season_id', $this->season->getKey()) + ->first(); + + $this->assertSame($userScore->total_score, (float) 10); // 10*1 + + $this->createRoomWithPlay(15); + + $userScore->refresh(); + $this->assertSame($userScore->total_score, 22.5); // 15*1 + 10*0.75 + + $this->createRoomWithPlay(25); + + $userScore->refresh(); + $this->assertSame($userScore->total_score, 41.25); // 25*1 + 15*0.75 + 10*0.5 + } + + public function testAddMultipleScoresWithChildrenRooms(): void + { + foreach ([1, 0.75, 0.5] as $factor) { + SeasonScoreFactor::factory()->create([ + 'factor' => $factor, + 'season_id' => $this->season, + ]); + } + + $firstRoom = $this->createRoomWithPlay(10); + + $userScore = UserSeasonScore::where('user_id', $this->user->getKey()) + ->where('season_id', $this->season->getKey()) + ->first(); + + $this->assertSame($userScore->total_score, (float) 10); // 10*1 + + $this->createRoomWithPlay(15, $firstRoom->getKey()); + + $userScore->refresh(); + $this->assertSame($userScore->total_score, (float) 15); // 15*1 + + $secondRoom = $this->createRoomWithPlay(20); + + $userScore->refresh(); + $this->assertSame($userScore->total_score, 31.25); // 20*1 + 15*0.75 + + $this->createRoomWithPlay(20, $secondRoom->getKey()); + + $userScore->refresh(); + $this->assertSame($userScore->total_score, 31.25); // 20*1 + 15*0.75 + + $thirdRoom = $this->createRoomWithPlay(10); + + $userScore->refresh(); + $this->assertSame($userScore->total_score, 36.25); // 20*1 + 15*0.75 + 10*0.5 + + $this->createRoomWithPlay(30, $thirdRoom->getKey()); + + $userScore->refresh(); + $this->assertSame($userScore->total_score, 52.5); // 30*1 + 20*0.75 + 15*0.5 + } + + public function testAddHigherScoreInChildRoom(): void + { + SeasonScoreFactor::factory()->create(['season_id' => $this->season]); + + $room = $this->createRoomWithPlay(10); + + $userScore = UserSeasonScore::where('user_id', $this->user->getKey()) + ->where('season_id', $this->season->getKey()) + ->first(); + + $this->assertSame($userScore->total_score, (float) 10); + + $this->createRoomWithPlay(15, $room->getKey()); + + $userScore->refresh(); + $this->assertSame($userScore->total_score, (float) 15); + } + + public function testAddHigherScoreInParentRoom(): void + { + SeasonScoreFactor::factory()->create(['season_id' => $this->season]); + + $room = $this->createRoomWithPlay(15); + + $userScore = UserSeasonScore::where('user_id', $this->user->getKey()) + ->where('season_id', $this->season->getKey()) + ->first(); + + $this->assertSame($userScore->total_score, (float) 15); + + $this->createRoomWithPlay(10, $room->getKey()); + + $userScore->refresh(); + $this->assertSame($userScore->total_score, (float) 15); + } + + public function testAddSameScoreInChildAndParentRoom(): void + { + SeasonScoreFactor::factory()->create(['season_id' => $this->season]); + + $room = $this->createRoomWithPlay(10); + + $userScore = UserSeasonScore::where('user_id', $this->user->getKey()) + ->where('season_id', $this->season->getKey()) + ->first(); + + $this->assertSame($userScore->total_score, (float) 10); + + $this->createRoomWithPlay(10, $room->getKey()); + + $userScore->refresh(); + $this->assertSame($userScore->total_score, (float) 10); + } + + public function testAddScoreInChildRoomOnly(): void + { + SeasonScoreFactor::factory()->create(['season_id' => $this->season]); + + $room = $this->createRoom(); + $this->createRoomWithPlay(10, $room->getKey()); + + $userScore = UserSeasonScore::where('user_id', $this->user->getKey()) + ->where('season_id', $this->season->getKey()) + ->first(); + + $this->assertSame($userScore->total_score, (float) 10); + } + + protected function setUp(): void + { + parent::setUp(); + + $this->season = Season::factory()->create(); + $this->user = User::factory()->create(); + } + + private function createRoom(?int $parentId = null): Room + { + $room = Room::factory()->create([ + 'category' => 'spotlight', + 'parent_id' => $parentId, + ]); + + SeasonRoom::factory()->create([ + 'room_id' => $room, + 'season_id' => $this->season, + ]); + + return $room; + } + + private function createRoomWithPlay(float $totalScore, ?int $parentId = null): Room + { + $room = $this->createRoom($parentId); + + $playlistItem = PlaylistItem::factory()->create([ + 'owner_id' => $room->host, + 'room_id' => $room, + ]); + + $this->roomAddPlay($this->user, $playlistItem, [ + 'passed' => true, + 'total_score' => $totalScore, + ]); + + return $room; + } +}