Finalize fake data improvements
|
@ -40,8 +40,8 @@ class Number
|
|||
*/
|
||||
public static function fractionStringFromFloat(float $value): string {
|
||||
$fraction = (string) Fraction::fromFloat($value);
|
||||
$fraction = str_replace('33333333/100000000', '1/3', $fraction);
|
||||
$fraction = str_replace('66666667/100000000', '2/3', $fraction);
|
||||
$fraction = str_replace(['33/100', '33333333/100000000'], '1/3', $fraction);
|
||||
$fraction = str_replace(['67/100', '66666667/100000000'], '2/3', $fraction);
|
||||
return $fraction;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -63,6 +63,7 @@ class Nutrients
|
|||
* - label: Human-readable name for the entry.
|
||||
* - unit: Unit of measure for the entry.
|
||||
* - weight: Sort weight for presentation.
|
||||
* - rdi: US FDA's recommended daily intake for adults (https://www.fda.gov/media/99059/download).
|
||||
*/
|
||||
public static function all(): Collection {
|
||||
return new Collection([
|
||||
|
@ -71,36 +72,42 @@ class Nutrients
|
|||
'label' => 'calories',
|
||||
'unit' => null,
|
||||
'weight' => 0,
|
||||
'rdi' => 2000,
|
||||
],
|
||||
'carbohydrates' => [
|
||||
'value' => 'carbohydrates',
|
||||
'label' => 'carbohydrates',
|
||||
'unit' => 'g',
|
||||
'weight' => 40,
|
||||
'rdi' => 275,
|
||||
],
|
||||
'cholesterol' => [
|
||||
'value' => 'cholesterol',
|
||||
'label' => 'cholesterol',
|
||||
'unit' => 'mg',
|
||||
'weight' => 20,
|
||||
'rdi' => 300,
|
||||
],
|
||||
'fat' => [
|
||||
'value' => 'fat',
|
||||
'label' => 'fat',
|
||||
'unit' => 'g',
|
||||
'weight' => 10,
|
||||
'rdi' => 78,
|
||||
],
|
||||
'protein' => [
|
||||
'value' => 'protein',
|
||||
'label' => 'protein',
|
||||
'unit' => 'g',
|
||||
'weight' => 50,
|
||||
'rdi' => 50,
|
||||
],
|
||||
'sodium' => [
|
||||
'value' => 'sodium',
|
||||
'label' => 'sodium',
|
||||
'unit' => 'mg',
|
||||
'weight' => 30,
|
||||
'rdi' => 2300,
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
|
|
@ -58,9 +58,9 @@ return [
|
|||
'endpoint' => env('AWS_ENDPOINT'),
|
||||
],
|
||||
|
||||
'wordlists' => [
|
||||
'seeder' => [
|
||||
'driver' => 'local',
|
||||
'root' => storage_path('wordlists'),
|
||||
'root' => storage_path('seeder'),
|
||||
],
|
||||
|
||||
],
|
||||
|
|
|
@ -6,7 +6,6 @@ use App\Models\Food;
|
|||
|
||||
use Database\Support\Words;
|
||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||
use Illuminate\Support\Arr;
|
||||
|
||||
class FoodFactory extends Factory
|
||||
{
|
||||
|
@ -22,22 +21,21 @@ class FoodFactory extends Factory
|
|||
public function definition(): array
|
||||
{
|
||||
return [
|
||||
'name' => Words::randomWords(Arr::random(['n', 'an']), TRUE),
|
||||
'detail' => $this->faker->optional()->sentence(2),
|
||||
'name' => Words::randomWords($this->faker->randomElement(['n', 'an'])),
|
||||
'detail' => $this->faker->boolean() ? Words::randomWords('a') : null,
|
||||
'brand' => $this->faker->optional()->word,
|
||||
'source' => $this->faker->optional()->url,
|
||||
'notes' => $this->faker->optional(0.25)->paragraph,
|
||||
'notes' => $this->faker->optional(0.25)->realText(),
|
||||
'serving_size' => $this->faker->numberBetween(1, 3),
|
||||
'serving_unit' => $this->faker->randomElement(['tsp', 'tbsp', 'cup']),
|
||||
'serving_weight' => $this->faker->numberBetween(5, 500),
|
||||
'serving_unit_name' => $this->faker->optional(0.25)->word,
|
||||
'calories' => $this->faker->randomFloat(1, 0, 100),
|
||||
'fat' => $this->faker->randomFloat(1, 0, 10),
|
||||
'cholesterol' => $this->faker->randomFloat(1, 0, 100),
|
||||
'sodium' => $this->faker->randomFloat(1, 0, 500),
|
||||
'carbohydrates' => $this->faker->randomFloat(1, 0, 20),
|
||||
'protein' => $this->faker->randomFloat(1, 0, 20),
|
||||
'tags' => Words::randomWords(Arr::random(['a', 'aa', 'aaa'])),
|
||||
'tags' => Words::randomWords($this->faker->randomElement(['a', 'aa', 'aaa']), TRUE),
|
||||
];
|
||||
}
|
||||
|
||||
|
|
|
@ -36,9 +36,9 @@ class IngredientAmountFactory extends Factory
|
|||
return [
|
||||
'ingredient_id' => $ingredient_factory,
|
||||
'ingredient_type' => $ingredient_type,
|
||||
'amount' => $this->faker->randomFloat(1, 1/3, 5),
|
||||
'amount' => $this->faker->randomElement([1/8, 1/4, 1/3, 1/2, 3/4, 1, 1.25, 1.5, 1.75, 2, 2.5, 3]),
|
||||
'unit' => $ingredient_unit,
|
||||
'detail' => $this->faker->boolean() ?: Words::randomWords('a'),
|
||||
'detail' => $this->faker->boolean() ? Words::randomWords('a') : null,
|
||||
'weight' => $this->faker->numberBetween(0, 50),
|
||||
'parent_id' => Recipe::factory(),
|
||||
'parent_type' => Recipe::class,
|
||||
|
|
|
@ -4,6 +4,7 @@ namespace Database\Factories;
|
|||
|
||||
use App\Models\JournalEntry;
|
||||
use App\Models\User;
|
||||
use Database\Support\Words;
|
||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||
|
||||
class JournalEntryFactory extends Factory
|
||||
|
@ -21,13 +22,13 @@ class JournalEntryFactory extends Factory
|
|||
return [
|
||||
'user_id' => User::factory(),
|
||||
'date' => $this->faker->dateTimeThisMonth,
|
||||
'summary' => $this->faker->realText(50),
|
||||
'summary' => Words::randomWords($this->faker->randomElement(['n', 'n, n', 'n, n, n'])),
|
||||
'calories' => $this->faker->randomFloat(1, 0, 500),
|
||||
'fat' => $this->faker->randomFloat(1, 0, 50),
|
||||
'cholesterol' => $this->faker->randomFloat(1, 0, 2000),
|
||||
'sodium' => $this->faker->randomFloat(1, 0, 2000),
|
||||
'carbohydrates' => $this->faker->randomFloat(1, 0, 100),
|
||||
'protein' => $this->faker->randomFloat(1, 0, 100),
|
||||
'fat' => $this->faker->randomFloat(1, 0, 20),
|
||||
'cholesterol' => $this->faker->randomFloat(1, 0, 200),
|
||||
'sodium' => $this->faker->randomFloat(1, 0, 500),
|
||||
'carbohydrates' => $this->faker->randomFloat(1, 0, 40),
|
||||
'protein' => $this->faker->randomFloat(1, 0, 20),
|
||||
'meal' => $this->faker->randomElement(['breakfast', 'lunch', 'dinner', 'snacks']),
|
||||
];
|
||||
}
|
||||
|
|
|
@ -24,15 +24,15 @@ class RecipeFactory extends Factory
|
|||
{
|
||||
$description = htmlspecialchars($this->faker->realText(500));
|
||||
return [
|
||||
'name' => Words::randomWords(Arr::random(['npan', 'npn', 'anpn']), TRUE),
|
||||
'name' => Words::randomWords(Arr::random(['npan', 'npn', 'anpn'])),
|
||||
'description' => "<p>{$description}</p>",
|
||||
'description_delta' => '{"ops":[{"insert":"' . $description . '\n"}]}"',
|
||||
'description_delta' => '{"ops":[{"insert":"' . htmlentities($description) . '\n"}]}"',
|
||||
'time_prep' => $this->faker->numberBetween(0, 20),
|
||||
'time_cook' => $this->faker->numberBetween(0, 90),
|
||||
'source' => $this->faker->optional()->url,
|
||||
'servings' => $this->faker->numberBetween(1, 10),
|
||||
'weight' => $this->faker->randomFloat(1, 60, 2000),
|
||||
'tags' => Words::randomWords(Arr::random(['a', 'aa', 'aaa'])),
|
||||
'tags' => Words::randomWords(Arr::random(['a', 'aa', 'aaa']), TRUE),
|
||||
];
|
||||
}
|
||||
|
||||
|
|
|
@ -19,8 +19,8 @@ class RecipeSeparatorFactory extends Factory
|
|||
{
|
||||
return [
|
||||
'container' => 'ingredients',
|
||||
'weight' => $this->faker->numberBetween(0, 100),
|
||||
'text' => $this->faker->optional()->realText(20),
|
||||
'weight' => $this->faker->numberBetween(0, 20),
|
||||
'text' => $this->faker->optional()->words(rand(1, 3), TRUE),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
namespace Database\Factories;
|
||||
|
||||
use App\Models\RecipeStep;
|
||||
use Database\Support\Words;
|
||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||
|
||||
class RecipeStepFactory extends Factory
|
||||
|
@ -17,9 +18,10 @@ class RecipeStepFactory extends Factory
|
|||
*/
|
||||
public function definition(): array
|
||||
{
|
||||
$word_combos = ['v', 'vn', 'van', 'vnpan', 'vanpn'];
|
||||
return [
|
||||
'number' => $this->faker->numberBetween(1, 50),
|
||||
'step' => $this->faker->realText(500),
|
||||
'step' => Words::randomWords($this->faker->randomElement($word_combos)),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,11 +4,16 @@ namespace Database\Seeders;
|
|||
|
||||
use App\Models\Food;
|
||||
use App\Models\Goal;
|
||||
use App\Models\IngredientAmount;
|
||||
use App\Models\JournalEntry;
|
||||
use App\Models\Recipe;
|
||||
use App\Models\User;
|
||||
use App\Support\Nutrients;
|
||||
use Illuminate\Database\Seeder;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class DatabaseSeeder extends Seeder
|
||||
|
@ -24,16 +29,52 @@ class DatabaseSeeder extends Seeder
|
|||
'name' => 'Admin',
|
||||
'remember_token' => Str::random(10),
|
||||
]);
|
||||
// @todo Make this more fine tuned for different macros.
|
||||
Goal::factory()->for($user)->count(5)->create();
|
||||
Food::factory()->count(100)->create();
|
||||
// @todo Create with media.
|
||||
Recipe::factory()
|
||||
->hasIngredientAmounts(rand(2, 20))
|
||||
|
||||
$goals = [];
|
||||
foreach (Nutrients::all() as $nutrient) {
|
||||
$goals[] = [
|
||||
'frequency' => 'daily',
|
||||
'name' => $nutrient['value'],
|
||||
'goal' => $nutrient['rdi'],
|
||||
];
|
||||
}
|
||||
Goal::factory()->for($user)->createMany($goals);
|
||||
|
||||
$foods = Food::factory()->count(100)->create();
|
||||
$recipes = Recipe::factory()
|
||||
->hasSteps(rand(5, 20))
|
||||
->hasIngredientSeparators(rand(0, 5))
|
||||
->count(50)
|
||||
->count(25)
|
||||
->create();
|
||||
JournalEntry::factory()->for($user)->count(100)->create();
|
||||
|
||||
$storage = Storage::disk('seeder');
|
||||
$photos = new Collection($storage->files('photos'));
|
||||
/** @var \App\Models\Recipe $recipe */
|
||||
foreach ($recipes as $recipe) {
|
||||
$ingredients = [];
|
||||
for ($i = 0; $i < rand(1, 20); $i++) {
|
||||
$ingredients[] = IngredientAmount::factory()
|
||||
->for($recipe, 'parent')
|
||||
->for($foods->random(), 'ingredient')
|
||||
->create([
|
||||
'weight' => $i,
|
||||
]);
|
||||
}
|
||||
$recipe->ingredientAmounts()->saveMany($ingredients);
|
||||
|
||||
$recipe->addMediaFromStream($storage->get($photos->pop()))
|
||||
->usingName($recipe->name)
|
||||
->usingFileName("{$recipe->slug}.jpg")
|
||||
->preservingOriginal()
|
||||
->toMediaCollection();
|
||||
}
|
||||
|
||||
for ($i = 0; $i <= 31; $i++) {
|
||||
JournalEntry::factory()
|
||||
->for($user)
|
||||
->count(rand(5, 12))
|
||||
->create(['date' => Carbon::now()->sub('day', $i)]);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,8 +26,8 @@ class Words
|
|||
}
|
||||
|
||||
$words = new Collection();
|
||||
$storage = Storage::disk('wordlists');
|
||||
foreach ($storage->files($method) as $file) {
|
||||
$storage = Storage::disk('seeder');
|
||||
foreach ($storage->files("wordlists/{$method}") as $file) {
|
||||
$contents = array_filter(explode("\n", $storage->get($file)));
|
||||
$words->push(...$contents);
|
||||
}
|
||||
|
@ -47,7 +47,7 @@ class Words
|
|||
* - p: preposition, and
|
||||
* - v: verb.
|
||||
*/
|
||||
public static function randomWords(string $format = 'an', $asText = false): array|string {
|
||||
public static function randomWords(string $format = 'an', $asArray = false): array|string {
|
||||
$words = [];
|
||||
foreach (str_split($format) as $type) {
|
||||
$words[] = match ($type) {
|
||||
|
@ -58,10 +58,10 @@ class Words
|
|||
default => NULL
|
||||
};
|
||||
}
|
||||
if ($asText) {
|
||||
$words = implode(' ', $words);
|
||||
if ($asArray) {
|
||||
return $words;
|
||||
}
|
||||
return $words;
|
||||
return implode(' ', $words);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
After Width: | Height: | Size: 192 KiB |
After Width: | Height: | Size: 295 KiB |
After Width: | Height: | Size: 239 KiB |
After Width: | Height: | Size: 177 KiB |
After Width: | Height: | Size: 107 KiB |
After Width: | Height: | Size: 328 KiB |
After Width: | Height: | Size: 692 KiB |
After Width: | Height: | Size: 235 KiB |
After Width: | Height: | Size: 349 KiB |
After Width: | Height: | Size: 266 KiB |
After Width: | Height: | Size: 370 KiB |
After Width: | Height: | Size: 438 KiB |
After Width: | Height: | Size: 275 KiB |
After Width: | Height: | Size: 257 KiB |
After Width: | Height: | Size: 160 KiB |
After Width: | Height: | Size: 176 KiB |
After Width: | Height: | Size: 577 KiB |
After Width: | Height: | Size: 415 KiB |
After Width: | Height: | Size: 488 KiB |
After Width: | Height: | Size: 157 KiB |
After Width: | Height: | Size: 330 KiB |
After Width: | Height: | Size: 272 KiB |
After Width: | Height: | Size: 202 KiB |
After Width: | Height: | Size: 360 KiB |
After Width: | Height: | Size: 310 KiB |