the browser-facing portion of osu!
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 Database\Factories;
7
8use App\Models\Beatmap;
9use App\Models\BeatmapDiscussion;
10use App\Models\BeatmapDiscussionPost;
11use App\Models\Beatmapset;
12use App\Models\BeatmapsetEvent;
13use App\Models\Forum\Topic;
14use App\Models\Genre;
15use App\Models\Language;
16use App\Models\User;
17
18class BeatmapsetFactory extends Factory
19{
20 protected $model = Beatmapset::class;
21
22 public function definition(): array
23 {
24 return [
25 'artist' => fn () => $this->faker->name(),
26 'title' => fn () => substr($this->faker->sentence(rand(0, 5)), 0, 80),
27 'source' => fn () => $this->faker->domainWord(),
28 'tags' => fn () => $this->faker->domainWord(),
29 'bpm' => rand(100, 200),
30 'approved' => rand(0, 1),
31 'play_count' => rand(0, 50000),
32 'favourite_count' => rand(0, 500),
33 'genre_id' => Genre::factory(),
34 'language_id' => Language::factory(),
35 'submit_date' => fn () => $this->faker->dateTime(),
36 'thread_id' => 0,
37 'user_id' => 0, // follow db default if no user specified; this is for other factories that depend on user_id.
38 'offset' => fn () => $this->faker->randomDigit(),
39
40 // depends on approved
41 'approved_date' => fn (array $attr) => $attr['approved'] > 0 ? now() : null,
42
43 'creator' => fn (array $attr) => User::find($attr['user_id'])?->username ?? $this->faker->userName(),
44
45 // depends on artist and title
46 'displaytitle' => fn (array $attr) => "{$attr['artist']}|{$attr['title']}",
47 ];
48 }
49
50 public function deleted()
51 {
52 return $this->state(['deleted_at' => now()]);
53 }
54
55 public function inactive()
56 {
57 return $this->state(['active' => 0]);
58 }
59
60 public function owner(?User $user = null)
61 {
62 return $this->state(['user_id' => $user ?? User::factory()]);
63 }
64
65 public function pending()
66 {
67 return $this->state([
68 'approved' => Beatmapset::STATES['pending'],
69 'approved_date' => null,
70 'queued_at' => null,
71 ]);
72 }
73
74 public function qualified(?\DateTimeInterface $approvedAt = null)
75 {
76 $approvedAt ??= now();
77
78 return $this->state([
79 'approved' => Beatmapset::STATES['qualified'],
80 'approved_date' => $approvedAt,
81 'queued_at' => $approvedAt,
82 ]);
83 }
84
85 public function withDescription(): static
86 {
87 // Like `$this->for(Topic::factory()->...)`, but called after making the model and creating
88 // child models so that they can be used as dependencies.
89 return $this->afterMaking(function (Beatmapset $beatmapset) {
90 $beatmapset->thread_id = Topic::factory()
91 ->state(['topic_poster' => $beatmapset->user_id])
92 ->withPost()
93 ->create()
94 ->getKey();
95 });
96 }
97
98 public function withDiscussion()
99 {
100 return $this
101 ->has(Beatmap::factory()->state(fn (array $attr, Beatmapset $set) => ['user_id' => $set->user_id]))
102 ->has(BeatmapDiscussion::factory()->general()->state(fn (array $attr, Beatmapset $set) => [
103 'user_id' => $set->user_id,
104 ]));
105 }
106
107 public function withHypes(?int $count = null)
108 {
109 $count ??= $GLOBALS['cfg']['osu']['beatmapset']['required_hype'];
110
111 return $this->has(
112 BeatmapDiscussion::factory()
113 ->state(fn () => [
114 'user_id' => User::factory(),
115 ])
116 ->general()
117 ->messageType('hype')
118 ->has(BeatmapDiscussionPost::factory())
119 ->count($count)
120 );
121 }
122
123 public function withNominations(?array $modes = null, ?int $count = null)
124 {
125 $count ??= $GLOBALS['cfg']['osu']['beatmapset']['required_nominations'];
126
127 return $this
128 ->state(['nominations' => $count])
129 ->has(BeatmapsetEvent::factory()
130 ->count($count)
131 ->state([
132 'comment' => ['modes' => $modes],
133 'type' => BeatmapsetEvent::NOMINATE,
134 'user_id' => User::factory()->withGroup('bng', array_keys(Beatmap::MODES)),
135 ]), 'events');
136 }
137
138 public function withBeatmaps(?string $ruleset = null, int $count = 1, ?User $guestMapper = null)
139 {
140 return $this
141 ->has(Beatmap::factory()
142 ->count($count)
143 ->ruleset($ruleset ?? array_rand(Beatmap::MODES))
144 ->state(fn (array $attr, Beatmapset $set) => [
145 'approved' => $set->approved,
146 'user_id' => $guestMapper?->getKey() ?? $set->user_id,
147 ]));
148 }
149}