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 Database\Factories\UserStatistics;
9
10use App\Models\User;
11use Database\Factories\Factory;
12
13abstract class ModelFactory extends Factory
14{
15 private static function randPlaycount(array $attr, float $min, float $max): int
16 {
17 return rand((int) ($attr['playcount'] * $min), (int) ($attr['playcount'] * $max));
18 }
19
20 private static function getUser(array $attr): ?User
21 {
22 return isset($attr['user_id'])
23 ? ($attr['user_id'] instanceof User
24 ? $attr['user_id']
25 : User::find($attr['user_id'])
26 ) : null;
27 }
28
29 public function definition(): array
30 {
31 return $this->generateStats();
32 }
33
34 private function generateStats(): array
35 {
36 return [
37 'accuracy_count' => rand(1000, 250000), // 1k to 250k. unsure what field is for
38 'accuracy_new' => (float) (rand(850000, 1000000)) / 10000, // 85.0000 - 100.0000
39 'accuracy_total' => rand(1000, 250000), // 1k to 250k. unsure what field is for
40 'count100' => rand(10000, 2000000), // 10k to 2mil
41 'count300' => rand(10000, 5000000), // 10k to 5mil
42 'count50' => rand(10000, 1000000), // 10k to 1mil
43 'countMiss' => rand(10000, 1000000), // 10k to 1mil
44 'level' => rand(1, 104),
45 'max_combo' => rand(500, 4000),
46 'playcount' => rand(1000, 250000), // 1k - 250k
47 'rank' => rand(1, 500000),
48 'rank_score' => (float) rand(1, 15000),
49 'rank_score_index' => rand(1, 500000),
50 'ranked_score' => (float) rand(500000, 2000000000) * 2, // 500k - 4bil
51
52 'accuracy' => fn (array $attr) => $attr['accuracy_new'] / 100,
53 'country_acronym' => fn (array $attr) => static::getUser($attr)?->country_acronym ?? '',
54 'exit_count' => fn (array $attr) => static::randPlaycount($attr, 0.2, 0.3),
55 'fail_count' => fn (array $attr) => static::randPlaycount($attr, 0.1, 0.2),
56 'total_score' => fn (array $attr) => $attr['ranked_score'] * 1.4,
57 'total_seconds_played' => fn (array $attr) => static::randPlaycount($attr, 120 * 0.3, 120 * 0.7),
58
59 // The multipliers should sum up to less than 1
60 'xh_rank_count' => fn (array $attr) => round($attr['playcount'] * 0.0003),
61 'x_rank_count' => fn (array $attr) => round($attr['playcount'] * 0.001),
62 'sh_rank_count' => fn (array $attr) => round($attr['playcount'] * 0.02),
63 's_rank_count' => fn (array $attr) => round($attr['playcount'] * 0.05),
64 'a_rank_count' => fn (array $attr) => round($attr['playcount'] * 0.2),
65 ];
66 }
67}