<commit_before><?php

namespace OpenDominion\Tests;

use Artisan;
use Carbon\Carbon;
use CoreDataSeeder;
use OpenDominion\Console\Commands\Game\DataSyncCommand;
use OpenDominion\Factories\DominionFactory;
use OpenDominion\Factories\RealmFactory;
use OpenDominion\Models\Dominion;
use OpenDominion\Models\Race;
use OpenDominion\Models\Realm;
use OpenDominion\Models\Round;
use OpenDominion\Models\User;
use OpenDominion\Services\Dominion\SelectorService;

trait CreatesData
{
    /**
     * Seeds the database with core data (races, units etc).
     */
    public function seedDatabase(): void
    {
        $this->seed(CoreDataSeeder::class);

        Artisan::call(DataSyncCommand::class);
    }

    /**
     * Creates a user for testing purposes.
     *
     * @param string|null $password
     * @param array $attributes
     * @return User
     */
    protected function createUser(?string $password = null, array $attributes = []): User
    {
        if ($password !== null) {
            $attributes['password'] = <PASSWORD>($password);
        }

        return factory(User::class)->create($attributes);
    }

    /**
     * Creates and impersonates a user for testing purposes.
     *
     * @param string|null $password
     * @param array $attributes
     * @return User
     */
    protected function createAndImpersonateUser(?string $password = null, array $attributes = []): User
    {
        $user = $this->createUser($password, $attributes);
        $this->be($user);
        return $user;
    }

    /**
     * Creates a round for testing purposes.
     *
     * @param string $startDate Carbon-parsable string
     * @param string $endDate Carbon-parsable string
     * @return Round
     */
    protected function createRound(string $startDate = 'today', string $endDate = '+50 days'): Round
    {
        // todo: RoundFactory

        $round = Round::create([
            'round_league_id' => 1,
            'number' => 1,
            'name' => 'Testing Round',
            'start_date' => new Carbon($startDate . ' midnight'),
            'end_date' => new Carbon($endDate . ' midnight'),
            'realm_size' => 12,
            'pack_size' => 6
        ]);

        return $round;
    }

    /**
     * Creates a realm for testing purposes.
     *
     * @param Round $round
     * @param string $alignment 'good' or 'evil'
     * @return Realm
     */
    protected function createRealm(Round $round, string $alignment = 'good'): Realm
    {
        // todo: RealmFactory

        $realm = Realm::create([
            'round_id' => $round->id,
            'alignment' => $alignment,
            'number' => 1,
            'name' => 'Testing Realm',
        ]);

        return $realm;
    }

    /**
     * Creates a dominion for testing purposes.
     *
     * @param User $user
     * @param Round $round
     * @param Race|null $race
     * @param Realm|null $realm
     * @return Dominion
     */
    protected function createDominion(User $user, Round $round, ?Race $race = null, ?Realm $realm = null): Dominion
    {
        $faker = \Faker\Factory::create();

        /** @var DominionFactory $dominionFactory */
        $dominionFactory = $this->app->make(DominionFactory::class);

        if ($realm === null) {
            /** @var RealmFactory $realmFactory */
            $realmFactory = $this->app->make(RealmFactory::class);

            $realm = $realmFactory->create(
                $round,
                $race->alignment ?? 'good'
            );
        }

        return $dominionFactory->create(
            $user,
            $realm,
            $race ?? Race::first(),
            $faker->name,
            $faker->company
        );
    }

    /**<commit_msg>Always use Human race in CreatesData::createDominion<commit_after><?php

namespace OpenDominion\Tests;

use Artisan;
use Carbon\Carbon;
use CoreDataSeeder;
use OpenDominion\Console\Commands\Game\DataSyncCommand;
use OpenDominion\Factories\DominionFactory;
use OpenDominion\Factories\RealmFactory;
use OpenDominion\Models\Dominion;
use OpenDominion\Models\Race;
use OpenDominion\Models\Realm;
use OpenDominion\Models\Round;
use OpenDominion\Models\User;
use OpenDominion\Services\Dominion\SelectorService;

trait CreatesData
{
    /**
     * Seeds the database with core data (races, units etc).
     */
    public function seedDatabase(): void
    {
        $this->seed(CoreDataSeeder::class);

        Artisan::call(DataSyncCommand::class);
    }

    /**
     * Creates a user for testing purposes.
     *
     * @param string|null $password
     * @param array $attributes
     * @return User
     */
    protected function createUser(?string $password = null, array $attributes = []): User
    {
        if ($password !== null) {
            $attributes['password'] = bcrypt($password);
        }

        return factory(User::class)->create($attributes);
    }

    /**
     * Creates and impersonates a user for testing purposes.
     *
     * @param string|null $password
     * @param array $attributes
     * @return User
     */
    protected function createAndImpersonateUser(?string $password = null, array $attributes = []): User
    {
        $user = $this->createUser($password, $attributes);
        $this->be($user);
        return $user;
    }

    /**
     * Creates a round for testing purposes.
     *
     * @param string $startDate Carbon-parsable string
     * @param string $endDate Carbon-parsable string
     * @return Round
     */
    protected function createRound(string $startDate = 'today', string $endDate = '+50 days'): Round
    {
        // todo: RoundFactory

        $round = Round::create([
            'round_league_id' => 1,
            'number' => 1,
            'name' => 'Testing Round',
            'start_date' => new Carbon($startDate . ' midnight'),
            'end_date' => new Carbon($endDate . ' midnight'),
            'realm_size' => 12,
            'pack_size' => 6
        ]);

        return $round;
    }

    /**
     * Creates a realm for testing purposes.
     *
     * @param Round $round
     * @param string $alignment 'good' or 'evil'
     * @return Realm
     */
    protected function createRealm(Round $round, string $alignment = 'good'): Realm
    {
        // todo: RealmFactory

        $realm = Realm::create([
            'round_id' => $round->id,
            'alignment' => $alignment,
            'number' => 1,
            'name' => 'Testing Realm',
        ]);

        return $realm;
    }

    /**
     * Creates a dominion for testing purposes.
     *
     * @param User $user
     * @param Round $round
     * @param Race|null $race
     * @param Realm|null $realm
     * @return Dominion
     */
    protected function createDominion(User $user, Round $round, ?Race $race = null, ?Realm $realm = null): Dominion
    {
        $faker = \Faker\Factory::create();

        /** @var DominionFactory $dominionFactory */
        $dominionFactory = $this->app->make(DominionFactory::class);

        if ($realm === null) {
            /** @var RealmFactory $realmFactory */
            $realmFactory = $this->app->make(RealmFactory::class);

            $realm = $realmFactory->create(
                $round,
                $race->alignment ?? 'good'
            );
        }

        return $dominionFactory->create(
            $user,
            $realm,
            $race ?? Race::where('name', 'Human')->firstOrFail(),
            $faker->name,
            $faker->company
        );
    }

    /**
{'fraction_non_alphanumeric': 0.1314209472981988, 'fraction_numerical': 0.002134756504336224, 'mean_word_length': 2.1416596814752724, 'pattern_counts': {'":': 0, '<': 6, '<?xml version=': 0, '>': 55, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1267905', 'n_tokens_mistral': 2251, 'n_tokens_neox': 2164, 'n_words': 520}