[
  {
    "path": ".editorconfig",
    "content": "root = true\n\n[*]\ncharset = utf-8\nend_of_line = lf\ninsert_final_newline = true\nindent_style = space\nindent_size = 4\ntrim_trailing_whitespace = true\n\n[*.md]\ntrim_trailing_whitespace = false\n\n[*.{yml,yaml}]\nindent_size = 2"
  },
  {
    "path": ".gitattributes",
    "content": "* text=auto\n*.css linguist-vendored\n*.scss linguist-vendored\n*.js linguist-vendored\nCHANGELOG.md export-ignore\n\n# Files to keep with LF endings, even on Windows\n*.sh text eol=lf\n/docker/cron/scheduler eol=lf\n/docker/mysql/my.cnf eol=lf\n/docker/nginx/conf.d/app.conf eol=lf\n/docker/php/local.ini eol=lf\n"
  },
  {
    "path": ".gitignore",
    "content": "/node_modules\n/public/hot\n/public/storage\n/public/css/app.css\n/public/fonts/\n/public/js/app.js\n/storage/*.key\n/vendor\n/.idea\n.env\n.phpunit.result.cache\ndocker-compose.override.yml\nHomestead.json\nHomestead.yaml\nnpm-debug.log\nyarn-error.log\n/.vagrant\n/public/mix-manifest.json\n"
  },
  {
    "path": ".styleci.yml",
    "content": "php:\n  preset: laravel\n  disabled:\n    - no_unused_imports\n  finder:\n    not-name:\n      - index.php\n      - server.php\njs:\n  finder:\n    not-name:\n      - webpack.mix.js\ncss: true"
  },
  {
    "path": ".travis.yml",
    "content": "language: php\n\nphp:\n  - 7.3\n\naddons:\n  chrome: stable\n\ninstall:\n  - cp .env.example .env\n  - travis_retry composer install --no-interaction --prefer-dist --no-suggest\n  - php artisan key:generate\n  - php artisan dusk:chrome-driver\n\nbefore_script:\n  - google-chrome-stable --headless --disable-gpu --remote-debugging-port=9222 http://localhost &\n  - touch database/database.sqlite\n  - php artisan serve &\n\nscript:\n  - vendor/bin/phpunit\n  - php artisan dusk\n"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "content": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nIn the interest of fostering an open and welcoming environment, we as\ncontributors and maintainers pledge to making participation in our project and\nour community a harassment-free experience for everyone, regardless of age, body\nsize, disability, ethnicity, sex characteristics, gender identity and expression,\nlevel of experience, education, socio-economic status, nationality, personal\nappearance, race, religion, or sexual identity and orientation.\n\n## Our Standards\n\nExamples of behavior that contributes to creating a positive environment\ninclude:\n\n* Using welcoming and inclusive language\n* Being respectful of differing viewpoints and experiences\n* Gracefully accepting constructive criticism\n* Focusing on what is best for the community\n* Showing empathy towards other community members\n\nExamples of unacceptable behavior by participants include:\n\n* The use of sexualized language or imagery and unwelcome sexual attention or\n advances\n* Trolling, insulting/derogatory comments, and personal or political attacks\n* Public or private harassment\n* Publishing others' private information, such as a physical or electronic\n address, without explicit permission\n* Other conduct which could reasonably be considered inappropriate in a\n professional setting\n\n## Our Responsibilities\n\nProject maintainers are responsible for clarifying the standards of acceptable\nbehavior and are expected to take appropriate and fair corrective action in\nresponse to any instances of unacceptable behavior.\n\nProject maintainers have the right and responsibility to remove, edit, or\nreject comments, commits, code, wiki edits, issues, and other contributions\nthat are not aligned to this Code of Conduct, or to ban temporarily or\npermanently any contributor for other behaviors that they deem inappropriate,\nthreatening, offensive, or harmful.\n\n## Scope\n\nThis Code of Conduct applies both within project spaces and in public spaces\nwhen an individual is representing the project or its community. Examples of\nrepresenting a project or community include using an official project e-mail\naddress, posting via an official social media account, or acting as an appointed\nrepresentative at an online or offline event. Representation of a project may be\nfurther defined and clarified by project maintainers.\n\n## Enforcement\n\nInstances of abusive, harassing, or otherwise unacceptable behavior may be\nreported by contacting the project team at mchekin@gmail.com. All\ncomplaints will be reviewed and investigated and will result in a response that\nis deemed necessary and appropriate to the circumstances. The project team is\nobligated to maintain confidentiality with regard to the reporter of an incident.\nFurther details of specific enforcement policies may be posted separately.\n\nProject maintainers who do not follow or enforce the Code of Conduct in good\nfaith may face temporary or permanent repercussions as determined by other\nmembers of the project's leadership.\n\n## Attribution\n\nThis Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,\navailable at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html\n\n[homepage]: https://www.contributor-covenant.org\n\nFor answers to common questions about this code of conduct, see\nhttps://www.contributor-covenant.org/faq\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# Contributing\n\nThanks for your interest in the project.\nYour contribution is highly appreciated.\nHere are our guidelines to contributing to the project.\n\n## Adding Feature / Improvement suggestions / Submitting bug report\nFeel free to suggest new features, propose improvements or submitting bug reports.\n\n- Open Issues tab\n- Create new Issue with an appropriate label\n\nEvent better if you create a pull request.\n\n## Creating a pull request\n- Fork the repository.\n- Create a new branch from the master branch:\n\n    - `git checkout -b brief-description`\n    \n- Commit and push your changes.\n- Submit a pull request through.\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2017 Michael Chekin\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "app/Console/Kernel.php",
    "content": "<?php\n\nnamespace App\\Console;\n\nuse App\\Models\\Character;\nuse Illuminate\\Console\\Scheduling\\Schedule;\nuse Illuminate\\Foundation\\Console\\Kernel as ConsoleKernel;\n\nclass Kernel extends ConsoleKernel\n{\n    /**\n     * The Artisan commands provided by your application.\n     *\n     * @var array\n     */\n    protected $commands = [\n        //\n    ];\n\n    /**\n     * Define the application's command schedule.\n     *\n     * @param  \\Illuminate\\Console\\Scheduling\\Schedule  $schedule\n     * @return void\n     */\n    protected function schedule(Schedule $schedule)\n    {\n        $schedule->call(function () {\n            Character::query()\n                ->whereColumn('hit_points', '<', 'total_hit_points')\n                ->increment('hit_points');\n        })->everyMinute();\n    }\n\n    /**\n     * Register the commands for the application.\n     *\n     * @return void\n     */\n    protected function commands()\n    {\n        $this->load(__DIR__.'/Commands');\n\n        require base_path('routes/console.php');\n    }\n}\n"
  },
  {
    "path": "app/Exceptions/Handler.php",
    "content": "<?php\n\nnamespace App\\Exceptions;\n\nuse Exception;\nuse Illuminate\\Foundation\\Exceptions\\Handler as ExceptionHandler;\nuse Illuminate\\Http\\Exceptions\\PostTooLargeException;\nuse Throwable;\n\nclass Handler extends ExceptionHandler\n{\n    /**\n     * A list of the exception types that are not reported.\n     *\n     * @var array\n     */\n    protected $dontReport = [\n        //\n    ];\n\n    /**\n     * A list of the inputs that are never flashed for validation exceptions.\n     *\n     * @var array\n     */\n    protected $dontFlash = [\n        'current_password',\n        'password',\n        'password_confirmation',\n    ];\n\n    /**\n     * Report or log an exception.\n     *\n     * This is a great spot to send exceptions to Sentry, Bugsnag, etc.\n     *\n     * @param  \\Throwable $exception\n     * @return void\n     */\n    public function register()\n    {\n        $this->reportable(function (Throwable $e) {\n            //\n        });\n    }\n\n    /**\n     * Render an exception into an HTTP response.\n     *\n     * @param  \\Illuminate\\Http\\Request  $request\n     * @param  \\Throwable  $exception\n     * @return \\Symfony\\Component\\HttpFoundation\\Response\n     *\n     * @throws \\Throwable\n     */\n    public function render($request, Throwable $exception)\n    {\n        if ($exception instanceof PostTooLargeException) {\n\n            return back()\n                ->withErrors([\n                    'message' => \"The file may not be greater than {$this->getMaxSizeInKiloBytes()} kilobytes\",\n                ]);\n        }\n\n        return parent::render($request, $exception);\n    }\n\n    private function getMaxSizeInKiloBytes(): float\n    {\n        return bytes_to_kilobytes(config('filesystems.max_size_in_bytes'));\n    }\n}\n"
  },
  {
    "path": "app/Http/Controllers/Api/ManageInventoryController.php",
    "content": "<?php\n\nnamespace App\\Http\\Controllers\\Api;\n\nuse App\\Http\\Controllers\\Controller;\nuse App\\Modules\\Equipment\\Application\\Services\\InventoryService;\nuse App\\Modules\\Equipment\\UI\\Http\\CommandMappers\\EquipItemCommandMapper;\nuse Exception;\nuse Illuminate\\Http\\JsonResponse;\nuse Illuminate\\Http\\Request;\nuse Illuminate\\Support\\Facades\\DB;\n\nclass ManageInventoryController extends Controller\n{\n    /**\n     * @var InventoryService\n     */\n    private $inventoryService;\n\n    public function __construct(InventoryService $inventoryService)\n    {\n        $this->inventoryService = $inventoryService;\n    }\n\n    public function equipItem(Request $request, EquipItemCommandMapper $commandMapper): JsonResponse\n    {\n        $command = $commandMapper->map($request);\n\n        try {\n\n            DB::transaction(function () use ($command) {\n                $this->inventoryService->equipItem($command);\n            });\n\n        } catch (Exception $exception) {\n\n            return response()->json([\n                'message' => 'Error equipping item: ' . $exception->getMessage()\n            ], 500);\n        }\n\n        return response()->json(['message' => 'Item equipped']);\n    }\n\n    public function unEquipItem(Request $request, EquipItemCommandMapper $commandMapper): JsonResponse\n    {\n        $command = $commandMapper->map($request);\n\n        try {\n\n            DB::transaction(function () use ($command) {\n                $this->inventoryService->unEquipItem($command);\n            });\n\n        } catch (Exception $exception) {\n\n            return response()->json([\n                'message' => 'Error un-equipping item: ' . $exception->getMessage()\n            ], 500);\n        }\n\n        return response()->json(['message' => 'Item un-equipped']);\n    }\n}\n"
  },
  {
    "path": "app/Http/Controllers/Api/ManageStoreController.php",
    "content": "<?php\n\nnamespace App\\Http\\Controllers\\Api;\n\nuse App\\Http\\Controllers\\Controller;\nuse App\\Modules\\Trade\\Application\\Services\\ManageStoreService;\nuse App\\Modules\\Trade\\UI\\Http\\CommandMappers\\ChangeItemPriceCommandMapper;\nuse App\\Modules\\Trade\\UI\\Http\\CommandMappers\\MoveItemToContainerCommandMapper;\nuse App\\Modules\\Trade\\UI\\Http\\CommandMappers\\MoveMoneyToContainerCommandMapper;\nuse Exception;\nuse Illuminate\\Http\\JsonResponse;\nuse Illuminate\\Http\\Request;\nuse Illuminate\\Support\\Facades\\DB;\n\nclass ManageStoreController extends Controller\n{\n    /**\n     * @var ManageStoreService\n     */\n    private $service;\n\n    public function __construct(ManageStoreService $service)\n    {\n        $this->service = $service;\n    }\n\n    public function changeItemPrice(Request $request, ChangeItemPriceCommandMapper $commandMapper): JsonResponse\n    {\n        $command = $commandMapper->map($request);\n\n        try {\n\n            DB::transaction(function () use ($command) {\n                $this->service->changeItemPrice($command);\n            });\n\n        } catch (Exception $exception) {\n\n            return response()->json([\n                'message' => 'Error changing item price: ' . $exception->getMessage()\n            ], 500);\n        }\n\n        return response()->json(['message' => 'Item price changed']);\n    }\n\n    public function moveItemToStore(Request $request, MoveItemToContainerCommandMapper $commandMapper): JsonResponse\n    {\n        $command = $commandMapper->map($request);\n\n        try {\n\n            DB::transaction(function () use ($command) {\n                $this->service->moveItemToStore($command);\n            });\n\n        } catch (Exception $exception) {\n\n            return response()->json([\n                'message' => 'Error moving item to store: ' . $exception->getMessage()\n            ], 500);\n        }\n\n        return response()->json(['message' => 'Item moved to store']);\n    }\n\n    public function moveItemToInventory(Request $request, MoveItemToContainerCommandMapper $commandMapper): JsonResponse\n    {\n        $command = $commandMapper->map($request);\n\n        try {\n\n            DB::transaction(function () use ($command) {\n                $this->service->moveItemToInventory($command);\n            });\n\n        } catch (Exception $exception) {\n\n            return response()->json([\n                'message' => 'Error moving item to inventory: ' . $exception->getMessage()\n            ], 500);\n        }\n\n        return  response()->json(['message' => 'Item moved to inventory']);\n    }\n\n    public function moveMoneyToStore(Request $request, MoveMoneyToContainerCommandMapper $commandMapper): JsonResponse\n    {\n        $command = $commandMapper->map($request);\n\n        try {\n\n            DB::transaction(function () use ($command) {\n                $this->service->moveMoneyToStore($command);\n            });\n\n        } catch (Exception $exception) {\n\n            return response()->json([\n                'message' => 'Error moving money to store: ' . $exception->getMessage()\n            ]);\n        }\n\n        return response()->json(['message' => 'Money moved to store']);\n    }\n\n    public function moveMoneyToInventory(Request $request, MoveMoneyToContainerCommandMapper $commandMapper): JsonResponse\n    {\n        $command = $commandMapper->map($request);\n\n        try {\n\n            DB::transaction(function () use ($command) {\n                $this->service->moveMoneyToInventory($command);\n            });\n\n        } catch (Exception $exception) {\n\n            return response()->json([\n                'message' => 'Error moving money to inventory: ' . $exception->getMessage()\n            ]);\n        }\n\n        return response()->json(['status' => 'Money moved to inventory']);\n    }\n}\n"
  },
  {
    "path": "app/Http/Controllers/Api/TradeController.php",
    "content": "<?php\n\nnamespace App\\Http\\Controllers\\Api;\n\nuse App\\Http\\Controllers\\Controller;\nuse App\\Modules\\Trade\\Application\\Services\\TradeService;\nuse App\\Modules\\Trade\\UI\\Http\\CommandMappers\\BuyItemCommandMapper;\nuse App\\Modules\\Trade\\UI\\Http\\CommandMappers\\SellItemCommandMapper;\nuse Exception;\nuse Illuminate\\Http\\JsonResponse;\nuse Illuminate\\Http\\Request;\nuse Illuminate\\Support\\Facades\\DB;\n\nclass TradeController extends Controller\n{\n    /**\n     * @var TradeService\n     */\n    private $service;\n\n    public function __construct(TradeService $service)\n    {\n        $this->service = $service;\n    }\n\n    public function buyItem(Request $request, BuyItemCommandMapper $commandMapper): JsonResponse\n    {\n        $command = $commandMapper->map($request);\n\n        try {\n\n            DB::transaction(function () use ($command) {\n                $this->service->buyItem($command);\n            });\n\n        } catch (Exception $exception) {\n\n            return response()->json([\n                'message' => 'Error buying item: ' . $exception->getMessage()\n            ], 500);\n        }\n\n        return response()->json(['message' => 'Item bought']);\n    }\n\n    public function sellItem(Request $request, SellItemCommandMapper $commandMapper): JsonResponse\n    {\n        $command = $commandMapper->map($request);\n\n        try {\n\n            DB::transaction(function () use ($command) {\n                $this->service->sellItem($command);\n            });\n\n        } catch (Exception $exception) {\n\n            return response()->json([\n                'message' => 'Error selling item: ' . $exception->getMessage()\n            ], 500);\n        }\n\n        return response()->json(['message' => 'Item bought']);\n    }\n}\n"
  },
  {
    "path": "app/Http/Controllers/Auth/ConfirmPasswordController.php",
    "content": "<?php\n\nnamespace App\\Http\\Controllers\\Auth;\n\nuse App\\Http\\Controllers\\Controller;\nuse Illuminate\\Foundation\\Auth\\ConfirmsPasswords;\n\nclass ConfirmPasswordController extends Controller\n{\n    /*\n    |--------------------------------------------------------------------------\n    | Confirm Password Controller\n    |--------------------------------------------------------------------------\n    |\n    | This controller is responsible for handling password confirmations and\n    | uses a simple trait to include the behavior. You're free to explore\n    | this trait and override any functions that require customization.\n    |\n    */\n\n    use ConfirmsPasswords;\n\n    /**\n     * Where to redirect users when the intended url fails.\n     *\n     * @var string\n     */\n    protected $redirectTo = '/home';\n\n    /**\n     * Create a new controller instance.\n     *\n     * @return void\n     */\n    public function __construct()\n    {\n        $this->middleware('auth');\n    }\n}\n"
  },
  {
    "path": "app/Http/Controllers/Auth/ForgotPasswordController.php",
    "content": "<?php\n\nnamespace App\\Http\\Controllers\\Auth;\n\nuse App\\Http\\Controllers\\Controller;\nuse Illuminate\\Foundation\\Auth\\SendsPasswordResetEmails;\n\nclass ForgotPasswordController extends Controller\n{\n    /*\n    |--------------------------------------------------------------------------\n    | Password Reset Controller\n    |--------------------------------------------------------------------------\n    |\n    | This controller is responsible for handling password reset emails and\n    | includes a trait which assists in sending these notifications from\n    | your application to your users. Feel free to explore this trait.\n    |\n    */\n\n    use SendsPasswordResetEmails;\n}\n"
  },
  {
    "path": "app/Http/Controllers/Auth/LoginController.php",
    "content": "<?php\n\nnamespace App\\Http\\Controllers\\Auth;\n\nuse App\\Http\\Controllers\\Controller;\nuse Illuminate\\Foundation\\Auth\\AuthenticatesUsers;\n\nclass LoginController extends Controller\n{\n    /*\n    |--------------------------------------------------------------------------\n    | Login Controller\n    |--------------------------------------------------------------------------\n    |\n    | This controller handles authenticating users for the application and\n    | redirecting them to your home screen. The controller uses a trait\n    | to conveniently provide its functionality to your applications.\n    |\n    */\n\n    use AuthenticatesUsers;\n\n    /**\n     * Where to redirect users after login.\n     *\n     * @var string\n     */\n    protected $redirectTo = '/home';\n\n    /**\n     * Create a new controller instance.\n     *\n     * @return void\n     */\n    public function __construct()\n    {\n        $this->middleware('guest')->except('logout');\n    }\n}\n"
  },
  {
    "path": "app/Http/Controllers/Auth/RegisterController.php",
    "content": "<?php\n\nnamespace App\\Http\\Controllers\\Auth;\n\nuse App\\Modules\\User\\Application\\Services\\UserService;\nuse App\\Modules\\User\\UI\\Http\\CommandMappers\\CreateUserCommandMapper;\nuse App\\Http\\Controllers\\Controller;\nuse App\\Models\\User;\nuse Illuminate\\Support\\Facades\\Validator;\nuse Illuminate\\Foundation\\Auth\\RegistersUsers;\n\nclass RegisterController extends Controller\n{\n    /*\n    |--------------------------------------------------------------------------\n    | Register Controller\n    |--------------------------------------------------------------------------\n    |\n    | This controller handles the registration of new users as well as their\n    | validation and creation. By default this controller uses a trait to\n    | provide this functionality without requiring any additional code.\n    |\n    */\n\n    use RegistersUsers;\n\n    /**\n     * Where to redirect users after registration.\n     *\n     * @var string\n     */\n    protected $redirectTo = '/home';\n\n    /**\n     * @var UserService\n     */\n    private $userService;\n    /**\n     * @var CreateUserCommandMapper\n     */\n    private $mapper;\n\n    /**\n     * Create a new controller instance.\n     *\n     * @param UserService $userService\n     * @param CreateUserCommandMapper $mapper\n     */\n    public function __construct(UserService $userService, CreateUserCommandMapper $mapper)\n    {\n        $this->middleware('guest');\n\n        $this->userService = $userService;\n        $this->mapper = $mapper;\n    }\n\n    /**\n     * Get a validator for an incoming registration request.\n     *\n     * @param  array  $data\n     * @return \\Illuminate\\Contracts\\Validation\\Validator\n     */\n    protected function validator(array $data)\n    {\n        return Validator::make($data, [\n            'name' => 'required|string|max:255',\n            'email' => 'required|string|email|max:255|unique:users',\n            'password' => 'required|string|min:8|confirmed',\n        ]);\n    }\n\n    /**\n     * Create a new user instance after a valid registration.\n     *\n     * @param  array $data\n     *\n     * @return User\n     */\n    protected function create(array $data)\n    {\n        $request = $this->mapper->map($data);\n\n        return $this->userService->create($request);\n    }\n}\n"
  },
  {
    "path": "app/Http/Controllers/Auth/ResetPasswordController.php",
    "content": "<?php\n\nnamespace App\\Http\\Controllers\\Auth;\n\nuse App\\Http\\Controllers\\Controller;\nuse Illuminate\\Foundation\\Auth\\ResetsPasswords;\n\nclass ResetPasswordController extends Controller\n{\n    /*\n    |--------------------------------------------------------------------------\n    | Password Reset Controller\n    |--------------------------------------------------------------------------\n    |\n    | This controller is responsible for handling password reset requests\n    | and uses a simple trait to include this behavior. You're free to\n    | explore this trait and override any methods you wish to tweak.\n    |\n    */\n\n    use ResetsPasswords;\n\n    /**\n     * Where to redirect users after resetting their password.\n     *\n     * @var string\n     */\n    protected $redirectTo = '/home';\n}\n"
  },
  {
    "path": "app/Http/Controllers/Auth/VerificationController.php",
    "content": "<?php\n\nnamespace App\\Http\\Controllers\\Auth;\n\nuse App\\Http\\Controllers\\Controller;\nuse Illuminate\\Foundation\\Auth\\VerifiesEmails;\n\nclass VerificationController extends Controller\n{\n    /*\n    |--------------------------------------------------------------------------\n    | Email Verification Controller\n    |--------------------------------------------------------------------------\n    |\n    | This controller is responsible for handling email verification for any\n    | user that recently registered with the application. Emails may also\n    | be re-sent if the user didn't receive the original email message.\n    |\n    */\n\n    use VerifiesEmails;\n\n    /**\n     * Where to redirect users after verification.\n     *\n     * @var string\n     */\n    protected $redirectTo = '/home';\n\n    /**\n     * Create a new controller instance.\n     *\n     * @return void\n     */\n    public function __construct()\n    {\n        $this->middleware('auth');\n        $this->middleware('signed')->only('verify');\n        $this->middleware('throttle:6,1')->only('verify', 'resend');\n    }\n}\n"
  },
  {
    "path": "app/Http/Controllers/BattleController.php",
    "content": "<?php\n\nnamespace App\\Http\\Controllers;\n\nuse App\\Models\\Battle;\n\nclass BattleController extends Controller\n{\n\n    public function __construct()\n    {\n        $this->middleware('auth', ['only' => ['show']]);\n        $this->middleware('has.character', ['only' => ['show']]);\n    }\n\n    public function show(string $battleId)\n    {\n        $battle = Battle::query()->findOrFail($battleId);\n\n        return view('battle.show', compact('battle'));\n    }\n}\n"
  },
  {
    "path": "app/Http/Controllers/CharacterBattleController.php",
    "content": "<?php\n\nnamespace App\\Http\\Controllers;\n\nuse App\\Models\\Character;\n\nclass CharacterBattleController extends Controller\n{\n    public function index(string $characterId)\n    {\n        $character = Character::query()->findOrFail($characterId);\n\n        return view('character.battle.index', compact('character'));\n    }\n}\n"
  },
  {
    "path": "app/Http/Controllers/CharacterController.php",
    "content": "<?php\n\nnamespace App\\Http\\Controllers;\n\nuse App\\Models\\Character;\nuse App\\Modules\\Character\\Application\\Services\\CharacterService;\nuse App\\Modules\\Character\\UI\\Http\\CommandMappers\\AttackCharacterCommandMapper;\nuse App\\Modules\\Character\\UI\\Http\\CommandMappers\\CreateCharacterCommandMapper;\nuse App\\Http\\Requests\\CreateCharacterRequest;\nuse App\\Http\\Requests\\UpdateCharacterAttributeRequest;\nuse App\\Modules\\Character\\UI\\Http\\CommandMappers\\IncreaseAttributeCommandMapper;\nuse App\\Modules\\Character\\UI\\Http\\CommandMappers\\MoveCharacterCommandMapper;\nuse App\\Models\\Race;\nuse Illuminate\\Contracts\\View\\View;\nuse Illuminate\\Http\\Request;\nuse Symfony\\Component\\HttpFoundation\\Response;\nuse Illuminate\\Support\\Facades\\Auth;\n\nclass CharacterController extends Controller\n{\n    /**\n     * @var CharacterService\n     */\n    private $characterService;\n\n    /**\n     * CharacterController constructor.\n     *\n     * @param CharacterService $characterService\n     */\n    public function __construct(CharacterService $characterService)\n    {\n        $this->middleware('auth');\n        $this->middleware('has.character', ['except' => ['create', 'store', 'update']]);\n        $this->middleware('owns.character', ['only' => ['update']]);\n        $this->middleware('no.character', ['only' => ['create', 'store']]);\n        $this->middleware('can.move.to.location', ['only' => ['move']]);\n        $this->middleware('can.attack', ['only' => ['attack']]);\n\n        $this->characterService = $characterService;\n    }\n\n    public function create(): View\n    {\n        $races = Race::all();\n        $user = Auth::user();\n\n        return view('character.create', compact('races', 'user'));\n    }\n\n    public function store(\n        CreateCharacterRequest $request,\n        CreateCharacterCommandMapper $commandMapper\n    ): Response {\n\n        $createCharacterCommand = $commandMapper->map($request);\n\n        $character = $this->characterService->create($createCharacterCommand);\n\n        return redirect()->route('character.show', ['character' => $character->getId()->toString()]);\n    }\n\n    public function show(string $characterId): View\n    {\n        $character = Character::query()->findOrFail($characterId);\n\n        return view('character.show', compact('character'));\n    }\n\n    public function update(\n        UpdateCharacterAttributeRequest $request,\n        IncreaseAttributeCommandMapper $commandMapper,\n        string $characterId\n    ): Response {\n\n        $increaseAttributeCommand = $commandMapper->map($characterId, $request);\n\n        $this->characterService->increaseAttribute($increaseAttributeCommand);\n\n        return back()->with('status', ucfirst($increaseAttributeCommand->getAttribute()) . ' + 1');\n    }\n\n    public function move(\n        MoveCharacterCommandMapper $commandMapper,\n        string $characterId,\n        string $locationId\n    ): Response {\n        $moveCharacterCommand = $commandMapper->map($characterId, $locationId);\n\n        $this->characterService->move($moveCharacterCommand);\n\n        return redirect()->route('location.show', $locationId);\n    }\n\n    public function attack(\n        string $defenderId,\n        Request $request,\n        AttackCharacterCommandMapper $commandMapper\n    ): Response {\n\n        $attackCharacterCommand = $commandMapper->map($request, $defenderId);\n\n        $battleId = $this->characterService->attack($attackCharacterCommand);\n\n        return redirect()->route('battle.show', $battleId->toString());\n    }\n}\n"
  },
  {
    "path": "app/Http/Controllers/CharacterMessageController.php",
    "content": "<?php\n\nnamespace App\\Http\\Controllers;\n\nuse App\\Models\\Character;\nuse App\\Modules\\Message\\Application\\Services\\MessageService;\nuse App\\Modules\\Message\\UI\\Http\\CommandMappers\\SendMessageCommandMapper;\nuse Illuminate\\Http\\Request;\n\nclass CharacterMessageController extends Controller\n{\n\n    public function __construct()\n    {\n        $this->middleware(['auth', 'has.character']);\n    }\n\n    public function index(string $characterId)\n    {\n        $character = Character::query()->findOrFail($characterId);\n\n        return view('character.message.index', compact('character'));\n    }\n\n    public function store(\n        string $characterId,\n        Request $request,\n        SendMessageCommandMapper $commandMapper,\n        MessageService $messageService\n    ) {\n        $sendMessageCommand = $commandMapper->map($request);\n\n        $messageService->send($sendMessageCommand);\n\n        return redirect()->route('character.message.index', $characterId);\n    }\n}\n"
  },
  {
    "path": "app/Http/Controllers/CharacterStoreController.php",
    "content": "<?php\n\nnamespace App\\Http\\Controllers;\n\nuse App\\Models\\Character;\nuse Illuminate\\Contracts\\View\\View;\nuse Illuminate\\Http\\Request;\n\nclass CharacterStoreController extends Controller\n{\n    public function __construct()\n    {\n        $this->middleware('auth');\n        $this->middleware('has.character');\n    }\n\n    public function index(Request $request, string $characterId): View\n    {\n        /** @var Character $customer */\n        $customer = $request->user()->character;\n\n        /** @var Character $trader */\n        $trader = Character::query()->findOrFail($characterId);\n\n        return view('trade.store.index', compact('customer', 'trader'));\n    }\n}\n"
  },
  {
    "path": "app/Http/Controllers/Controller.php",
    "content": "<?php\n\nnamespace App\\Http\\Controllers;\n\nuse Illuminate\\Foundation\\Bus\\DispatchesJobs;\nuse Illuminate\\Routing\\Controller as BaseController;\nuse Illuminate\\Foundation\\Validation\\ValidatesRequests;\nuse Illuminate\\Foundation\\Auth\\Access\\AuthorizesRequests;\n\nclass Controller extends BaseController\n{\n    use AuthorizesRequests, DispatchesJobs, ValidatesRequests;\n}\n"
  },
  {
    "path": "app/Http/Controllers/InventoryController.php",
    "content": "<?php\n\nnamespace App\\Http\\Controllers;\n\nuse App\\Models\\Character;\nuse App\\Modules\\Equipment\\Application\\Services\\InventoryService;\nuse App\\Modules\\Equipment\\UI\\Http\\CommandMappers\\EquipItemCommandMapper;\nuse App\\Modules\\Level\\Application\\Services\\LevelService;\nuse Exception;\nuse Illuminate\\Contracts\\View\\View;\nuse Illuminate\\Http\\RedirectResponse;\nuse Illuminate\\Http\\Request;\nuse Illuminate\\Support\\Facades\\DB;\n\nclass InventoryController extends Controller\n{\n    /**\n     * @var InventoryService\n     */\n    private $inventoryService;\n\n    public function __construct(InventoryService $inventoryService)\n    {\n        $this->middleware('auth');\n\n        $this->inventoryService = $inventoryService;\n    }\n\n    public function index(Request $request, LevelService $levelService): View\n    {\n        /** @var Character $character */\n        $character = $request->user()->character;\n\n        $level = $levelService->getLevel($character->getLevelNumber());\n\n        return view('character.inventory.index', ['character' => $character, 'level' => $level]);\n    }\n\n    public function equipItem(Request $request, EquipItemCommandMapper $commandMapper): RedirectResponse\n    {\n        $command = $commandMapper->map($request);\n\n        try {\n\n            DB::transaction(function () use ($command) {\n                $this->inventoryService->equipItem($command);\n            });\n\n        } catch (Exception $exception) {\n\n            return redirect()->back()->withErrors([\n                'message' => 'Error equipping item'\n            ]);\n        }\n\n        return redirect()->back()->with('status', 'Item equipped');\n    }\n\n    public function unEquipItem(Request $request, EquipItemCommandMapper $commandMapper): RedirectResponse\n    {\n        $command = $commandMapper->map($request);\n\n        try {\n\n            DB::transaction(function () use ($command) {\n                $this->inventoryService->unEquipItem($command);\n            });\n\n        } catch (Exception $exception) {\n\n            return redirect()->back()->withErrors([\n                'message' => 'Error un-equipping item'\n            ]);\n        }\n\n        return redirect()->back()->with('status', 'Item un-equipped');\n    }\n}\n"
  },
  {
    "path": "app/Http/Controllers/ItemCreateController.php",
    "content": "<?php\n\nnamespace App\\Http\\Controllers;\n\nuse App\\Http\\Requests\\CreateItemRequest;\nuse App\\Modules\\Equipment\\Application\\Services\\ItemService;\nuse App\\Modules\\Equipment\\UI\\Http\\CommandMappers\\CreateItemCommandMapper;\nuse Illuminate\\Http\\Response;\n\nclass ItemCreateController extends Controller\n{\n    /**\n     * @var ItemService\n     */\n    private $itemService;\n\n    public function __construct(ItemService $itemService)\n    {\n        $this->middleware('auth');\n        $this->middleware('has.character');\n        $this->middleware('is.admin');\n\n        $this->itemService = $itemService;\n    }\n\n    public function store(\n        CreateItemRequest $request,\n        CreateItemCommandMapper $commandMapper\n    ): Response {\n\n        $createItemCommand = $commandMapper->map($request);\n\n        $this->itemService->create($createItemCommand);\n\n        return redirect()->back();\n    }\n}\n"
  },
  {
    "path": "app/Http/Controllers/LocationController.php",
    "content": "<?php\n\nnamespace App\\Http\\Controllers;\n\nuse App\\Models\\Location;\n\nclass LocationController extends Controller\n{\n\n    public function __construct()\n    {\n        $this->middleware('auth', ['only' => ['show']]);\n        $this->middleware('has.character', ['only' => ['show']]);\n        $this->middleware('character.location', ['only' => ['show']]);\n    }\n\n    public function show(string $locationId)\n    {\n        /** @var Location $location */\n        $location = Location::query()\n            ->with('characters.race')\n            ->with('characters.user')\n            ->with('adjacentLocations')\n            ->findOrFail($locationId);\n\n        return view('location.show', compact('location'));\n    }\n}\n"
  },
  {
    "path": "app/Http/Controllers/MessageController.php",
    "content": "<?php\n\nnamespace App\\Http\\Controllers;\n\nuse Illuminate\\View\\View;\n\nclass MessageController extends Controller\n{\n    public function __construct()\n    {\n        $this->middleware(['auth', 'has.character']);\n    }\n\n    public function index(): View\n    {\n        return view('message.index');\n    }\n}\n"
  },
  {
    "path": "app/Http/Controllers/OwnStoreController.php",
    "content": "<?php\n\nnamespace App\\Http\\Controllers;\n\nuse App\\Models\\Character;\nuse Illuminate\\Contracts\\View\\View;\nuse Illuminate\\Http\\Request;\n\nclass OwnStoreController extends Controller\n{\n    public function __construct()\n    {\n        $this->middleware('auth');\n        $this->middleware('has.character');\n    }\n\n    public function index(Request $request): View\n    {\n        /** @var Character $character */\n        $character = $request->user()->character;\n\n        return view('trade.own_store.index', compact('character'));\n    }\n}\n"
  },
  {
    "path": "app/Http/Controllers/ProfilePictureController.php",
    "content": "<?php\n\nnamespace App\\Http\\Controllers;\n\nuse App\\Http\\Requests\\UploadImageRequest;\nuse App\\Modules\\Character\\Domain\\CharacterId;\nuse App\\Modules\\Image\\Application\\Services\\ProfilePictureService;\nuse App\\Modules\\Image\\UI\\Http\\CommandMappers\\AddImageCommandMapper;\n\nclass ProfilePictureController extends Controller\n{\n    public function __construct()\n    {\n        $this->middleware('owns.character');\n    }\n\n    public function store(\n        string $characterId,\n        UploadImageRequest $request,\n        ProfilePictureService $profilePictureService,\n        AddImageCommandMapper $commandMapper\n    ) {\n        $addImageCommand = $commandMapper->map($characterId, $request->file('file'));\n\n        $profilePictureService->update($addImageCommand);\n\n        return back()->with('status', 'Profile picture has been changed');\n    }\n\n    public function destroy(\n        string $characterId,\n        ProfilePictureService $profilePictureService\n    ) {\n        $profilePictureService->delete(CharacterId::fromString($characterId));\n\n        return back()->with('status', 'Profile picture has been deleted');\n    }\n}\n"
  },
  {
    "path": "app/Http/Kernel.php",
    "content": "<?php\n\nnamespace App\\Http;\n\nuse Illuminate\\Foundation\\Http\\Kernel as HttpKernel;\n\nclass Kernel extends HttpKernel\n{\n    /**\n     * The application's global HTTP middleware stack.\n     *\n     * These middleware are run during every request to your application.\n     *\n     * @var array\n     */\n    protected $middleware = [\n        // \\App\\Http\\Middleware\\TrustHosts::class,\n        \\App\\Http\\Middleware\\TrustProxies::class,\n        \\Fruitcake\\Cors\\HandleCors::class,\n        \\App\\Http\\Middleware\\PreventRequestsDuringMaintenance::class,\n        \\Illuminate\\Foundation\\Http\\Middleware\\ValidatePostSize::class,\n        \\App\\Http\\Middleware\\TrimStrings::class,\n        \\Illuminate\\Foundation\\Http\\Middleware\\ConvertEmptyStringsToNull::class,\n    ];\n\n    /**\n     * The application's route middleware groups.\n     *\n     * @var array\n     */\n    protected $middlewareGroups = [\n        'web' => [\n            \\App\\Http\\Middleware\\EncryptCookies::class,\n            \\Illuminate\\Cookie\\Middleware\\AddQueuedCookiesToResponse::class,\n            \\Illuminate\\Session\\Middleware\\StartSession::class,\n            // \\Illuminate\\Session\\Middleware\\AuthenticateSession::class,\n            \\Illuminate\\View\\Middleware\\ShareErrorsFromSession::class,\n            \\App\\Http\\Middleware\\VerifyCsrfToken::class,\n            \\Illuminate\\Routing\\Middleware\\SubstituteBindings::class,\n        ],\n\n        'api' => [\n            'throttle:api',\n            \\Illuminate\\Routing\\Middleware\\SubstituteBindings::class,\n        ],\n    ];\n\n    /**\n     * The application's route middleware.\n     *\n     * These middleware may be assigned to groups or used individually.\n     *\n     * @var array\n     */\n    protected $routeMiddleware = [\n        'auth' => \\App\\Http\\Middleware\\Authenticate::class,\n        'auth.basic' => \\Illuminate\\Auth\\Middleware\\AuthenticateWithBasicAuth::class,\n        'cache.headers' => \\Illuminate\\Http\\Middleware\\SetCacheHeaders::class,\n        'can' => \\Illuminate\\Auth\\Middleware\\Authorize::class,\n        'guest' => \\App\\Http\\Middleware\\RedirectIfAuthenticated::class,\n        'password.confirm' => \\Illuminate\\Auth\\Middleware\\RequirePassword::class,\n        'signed' => \\Illuminate\\Routing\\Middleware\\ValidateSignature::class,\n        'throttle' => \\Illuminate\\Routing\\Middleware\\ThrottleRequests::class,\n        'verified' => \\Illuminate\\Auth\\Middleware\\EnsureEmailIsVerified::class,\n        'character.location' => \\App\\Http\\Middleware\\IsCharacterLocation::class,\n        'has.character' => \\App\\Http\\Middleware\\HasCharacter::class,\n        'can.move.to.location' => \\App\\Http\\Middleware\\CanMoveToLocation::class,\n        'can.attack' => \\App\\Http\\Middleware\\CanAttack::class,\n        'no.character' => \\App\\Http\\Middleware\\NoCharacterYet::class,\n        'owns.character' => \\App\\Http\\Middleware\\UserOwnsCharacter::class,\n        'is.admin' => \\App\\Http\\Middleware\\IsAdmin::class,\n    ];\n}\n"
  },
  {
    "path": "app/Http/Middleware/Authenticate.php",
    "content": "<?php\n\nnamespace App\\Http\\Middleware;\n\nuse Illuminate\\Auth\\Middleware\\Authenticate as Middleware;\n\nclass Authenticate extends Middleware\n{\n    /**\n     * Get the path the user should be redirected to when they are not authenticated.\n     *\n     * @param  \\Illuminate\\Http\\Request  $request\n     * @return string\n     */\n    protected function redirectTo($request)\n    {\n        if (! $request->expectsJson()) {\n            return route('login');\n        }\n    }\n}\n"
  },
  {
    "path": "app/Http/Middleware/CanAttack.php",
    "content": "<?php\n\nnamespace App\\Http\\Middleware;\n\nuse App\\Models\\Character;\nuse App\\Models\\User;\nuse Closure;\nuse Illuminate\\Http\\Request;\n\nclass CanAttack\n{\n    /**\n     * Handle an incoming request.\n     *\n     * @param  Request  $request\n     * @param  Closure  $next\n     * @return mixed\n     */\n    public function handle($request, Closure $next)\n    {\n        /** @var Character $targetCharacter */\n        $targetCharacter = Character::query()->findOrFail($request->route('character'));\n\n        /** @var User $user */\n        $user = $request->user();\n        $currentUserCharacter = $user->getCharacter();\n\n        if (!$currentUserCharacter->isAlive()) {\n            return redirect()->back()->withErrors([\n                'message' => 'You cannot attack when your character is knocked out',\n            ]);\n        }\n\n        if (!$targetCharacter->isAlive()) {\n            return redirect()->back()->withErrors([\n                'message' => 'You cannot attack a knocked out character',\n            ]);\n        }\n\n        if ($targetCharacter->getId() === $currentUserCharacter->getId()) {\n            return redirect()->back()->withErrors([\n                'message' => 'You cannot attack yourself',\n            ]);\n        }\n\n        return $next($request);\n    }\n}\n"
  },
  {
    "path": "app/Http/Middleware/CanMoveToLocation.php",
    "content": "<?php\n\nnamespace App\\Http\\Middleware;\n\nuse App\\Models\\Character;\nuse App\\Models\\Location;\nuse Closure;\nuse Illuminate\\Http\\Request;\nuse Illuminate\\Support\\Facades\\Auth;\n\nclass CanMoveToLocation\n{\n    /**\n     * Handle an incoming request.\n     *\n     * @param  Request  $request\n     * @param  Closure  $next\n     * @return mixed\n     */\n    public function handle($request, Closure $next)\n    {\n        /** @var Character $character */\n        $character = Character::query()->findOrFail($request->route('character'));\n\n        /** @var Location $location */\n        $location = Location::query()->findOrFail($request->route('location'));\n\n        /** @var Location $characterLocation */\n        $characterLocation = $character->location;\n\n        // if this character does not belong to the logged in user\n        if (Auth::user()->id !== $character->user->id || !$characterLocation->isAdjacentLocation($location)) {\n            return redirect()->route('location.show', $location->getId());\n        }\n\n        return $next($request);\n    }\n}\n"
  },
  {
    "path": "app/Http/Middleware/EncryptCookies.php",
    "content": "<?php\n\nnamespace App\\Http\\Middleware;\n\nuse Illuminate\\Cookie\\Middleware\\EncryptCookies as Middleware;\n\nclass EncryptCookies extends Middleware\n{\n    /**\n     * The names of the cookies that should not be encrypted.\n     *\n     * @var array\n     */\n    protected $except = [\n        //\n    ];\n}\n"
  },
  {
    "path": "app/Http/Middleware/HasCharacter.php",
    "content": "<?php\n\nnamespace App\\Http\\Middleware;\n\nuse App\\Models\\User;\nuse Closure;\n\nclass HasCharacter\n{\n    /**\n     * Handle an incoming request.\n     *\n     * @param  \\Illuminate\\Http\\Request  $request\n     * @param  \\Closure  $next\n     * @return mixed\n     */\n    public function handle($request, Closure $next)\n    {\n        /** @var User $user */\n        $user = $request->user();\n\n        if ($user && !$user->hasCharacter()) {\n            return redirect()->route('character.create');\n        }\n\n        return $next($request);\n    }\n}\n"
  },
  {
    "path": "app/Http/Middleware/IsAdmin.php",
    "content": "<?php\n\nnamespace App\\Http\\Middleware;\n\nuse App\\Models\\User;\nuse Closure;\n\nclass IsAdmin\n{\n    /**\n     * Handle an incoming request.\n     *\n     * @param  \\Illuminate\\Http\\Request  $request\n     * @param  \\Closure  $next\n     * @return mixed\n     */\n    public function handle($request, Closure $next)\n    {\n        /** @var User $user */\n        $user = $request->user();\n\n        if ($user && $user->hasRole('admin')) {\n            return redirect()->back();\n        }\n\n        return $next($request);\n    }\n}\n"
  },
  {
    "path": "app/Http/Middleware/IsCharacterLocation.php",
    "content": "<?php\n\nnamespace App\\Http\\Middleware;\n\nuse App\\Models\\User;\nuse Closure;\n\nclass IsCharacterLocation\n{\n    /**\n     * Handle an incoming request.\n     *\n     * @param  \\Illuminate\\Http\\Request $request\n     * @param  \\Closure $next\n     * @return mixed\n     */\n    public function handle($request, Closure $next)\n    {\n        /** @var User $user */\n        $user = $request->user();\n        $locationId = $user->character->getLocationId();\n\n        if ($user && $user->hasCharacter() && $locationId !== $request->route('location')) {\n            return redirect()->route('location.show', $locationId);\n        }\n\n        return $next($request);\n    }\n}\n"
  },
  {
    "path": "app/Http/Middleware/NoCharacterYet.php",
    "content": "<?php\n\nnamespace App\\Http\\Middleware;\n\nuse App\\Models\\User;\nuse Closure;\n\nclass NoCharacterYet\n{\n    /**\n     * Handle an incoming request.\n     *\n     * @param  \\Illuminate\\Http\\Request  $request\n     * @param  \\Closure  $next\n     * @return mixed\n     */\n    public function handle($request, Closure $next)\n    {\n        /** @var User $user */\n        $user = $request->user();\n\n        if ($user && $user->hasCharacter()) {\n            return redirect('/home');\n        }\n\n        return $next($request);\n    }\n}\n"
  },
  {
    "path": "app/Http/Middleware/PreventRequestsDuringMaintenance.php",
    "content": "<?php\n\nnamespace App\\Http\\Middleware;\n\nuse Illuminate\\Foundation\\Http\\Middleware\\PreventRequestsDuringMaintenance as Middleware;\n\nclass PreventRequestsDuringMaintenance extends Middleware\n{\n    /**\n     * The URIs that should be reachable while maintenance mode is enabled.\n     *\n     * @var array\n     */\n    protected $except = [\n        //\n    ];\n}"
  },
  {
    "path": "app/Http/Middleware/RedirectIfAuthenticated.php",
    "content": "<?php\n\nnamespace App\\Http\\Middleware;\n\nuse App\\Providers\\RouteServiceProvider;\nuse Closure;\nuse Illuminate\\Http\\Request;\nuse Illuminate\\Support\\Facades\\Auth;\n\nclass RedirectIfAuthenticated\n{\n    /**\n     * Handle an incoming request.\n     *\n     * @param  \\Illuminate\\Http\\Request  $request\n     * @param  \\Closure  $next\n     * @param  string|null  ...$guards\n     * @return mixed\n     */\n    public function handle(Request $request, Closure $next, ...$guards)\n    {\n        $guards = empty($guards) ? [null] : $guards;\n\n        foreach ($guards as $guard) {\n            if (Auth::guard($guard)->check()) {\n                return redirect(RouteServiceProvider::HOME);\n            }\n        }\n\n        return $next($request);\n    }\n}"
  },
  {
    "path": "app/Http/Middleware/TrimStrings.php",
    "content": "<?php\n\nnamespace App\\Http\\Middleware;\n\nuse Illuminate\\Foundation\\Http\\Middleware\\TrimStrings as Middleware;\n\nclass TrimStrings extends Middleware\n{\n    /**\n     * The names of the attributes that should not be trimmed.\n     *\n     * @var array\n     */\n    protected $except = [\n        'current_password',\n        'password',\n        'password_confirmation',\n    ];\n}\n"
  },
  {
    "path": "app/Http/Middleware/TrustHosts.php",
    "content": "<?php\n\nnamespace App\\Http\\Middleware;\n\nuse Illuminate\\Http\\Middleware\\TrustHosts as Middleware;\n\nclass TrustHosts extends Middleware\n{\n    /**\n     * Get the host patterns that should be trusted.\n     *\n     * @return array\n     */\n    public function hosts()\n    {\n        return [\n            $this->allSubdomainsOfApplicationUrl(),\n        ];\n    }\n}"
  },
  {
    "path": "app/Http/Middleware/TrustProxies.php",
    "content": "<?php\n\nnamespace App\\Http\\Middleware;\n\nuse Fideloper\\Proxy\\TrustProxies as Middleware;\nuse Illuminate\\Http\\Request;\n\nclass TrustProxies extends Middleware\n{\n    /**\n     * The trusted proxies for this application.\n     *\n     * @var array|string|null\n     */\n    protected $proxies;\n\n    /**\n     * The headers that should be used to detect proxies.\n     *\n     * @var int\n     */\n    protected $headers = Request::HEADER_X_FORWARDED_FOR | Request::HEADER_X_FORWARDED_HOST | Request::HEADER_X_FORWARDED_PORT | Request::HEADER_X_FORWARDED_PROTO | Request::HEADER_X_FORWARDED_AWS_ELB;\n}"
  },
  {
    "path": "app/Http/Middleware/UpdateLastUserActivity.php",
    "content": "<?php\n\nnamespace App\\Http\\Middleware;\n\nuse App\\Models\\User;\nuse Closure;\n\nclass UpdateLastUserActivity\n{\n    /**\n     * Handle an incoming request.\n     *\n     * @param  \\Illuminate\\Http\\Request  $request\n     * @param  \\Closure  $next\n     * @return mixed\n     */\n    public function handle($request, Closure $next)\n    {\n        /** @var User $user */\n        $user = $request->user();\n        if($user) {\n\n            $user->updateLastUserActivity();\n        }\n\n        return $next($request);\n    }\n}\n"
  },
  {
    "path": "app/Http/Middleware/UserOwnsCharacter.php",
    "content": "<?php\n\nnamespace App\\Http\\Middleware;\n\nuse App\\Models\\Character;\nuse App\\Models\\User;\nuse Closure;\n\nclass UserOwnsCharacter\n{\n    /**\n     * Handle an incoming request.\n     *\n     * @param  \\Illuminate\\Http\\Request  $request\n     * @param  \\Closure  $next\n     * @return mixed\n     */\n    public function handle($request, Closure $next)\n    {\n        /** @var User $user */\n        $user = $request->user();\n\n        /** @var Character $character */\n        $character = Character::query()->findOrFail($request->route('character'));\n\n        if ($user && !$user->hasThisCharacter($character)) {\n            return redirect()->back();\n        }\n\n        return $next($request);\n    }\n}\n"
  },
  {
    "path": "app/Http/Middleware/VerifyCsrfToken.php",
    "content": "<?php\n\nnamespace App\\Http\\Middleware;\n\nuse Closure;\nuse Illuminate\\Foundation\\Http\\Middleware\\VerifyCsrfToken as Middleware;\nuse Illuminate\\Session\\TokenMismatchException;\n\nclass VerifyCsrfToken extends Middleware\n{\n    /**\n     * The URIs that should be excluded from CSRF verification.\n     *\n     * @var array\n     */\n    protected $except = [\n        //\n    ];\n\n    public function handle($request, Closure $next)\n    {\n        try {\n            return parent::handle($request, $next);\n        }\n        catch (TokenMismatchException $exception) {\n            return redirect()->back()->withErrors([\n                'message' => 'Your Session have expired. Try again.',\n            ]);\n        }\n    }\n}\n"
  },
  {
    "path": "app/Http/Requests/CreateCharacterRequest.php",
    "content": "<?php\n\nnamespace App\\Http\\Requests;\n\nuse Illuminate\\Foundation\\Http\\FormRequest;\n\nclass CreateCharacterRequest extends FormRequest\n{\n    /**\n     * Determine if the user is authorized to make this request.\n     *\n     * @return bool\n     */\n    public function authorize()\n    {\n        return true;\n    }\n\n    /**\n     * Get the validation rules that apply to the request.\n     *\n     * @return array\n     */\n    public function rules()\n    {\n        return [\n            'name' => 'required|unique:characters,name|min:2',\n            'gender' => 'required|in:male,female',\n            'race_id' => 'required|integer',\n        ];\n    }\n}\n"
  },
  {
    "path": "app/Http/Requests/CreateItemRequest.php",
    "content": "<?php\n\nnamespace App\\Http\\Requests;\n\nuse Illuminate\\Foundation\\Http\\FormRequest;\n\nclass CreateItemRequest extends FormRequest\n{\n    /**\n     * Determine if the user is authorized to make this request.\n     *\n     * @return bool\n     */\n    public function authorize()\n    {\n        return true;\n    }\n\n    /**\n     * Get the validation rules that apply to the request.\n     *\n     * @return array\n     */\n    public function rules()\n    {\n        return [\n            'item_prototype_id' => 'required',\n        ];\n    }\n}\n"
  },
  {
    "path": "app/Http/Requests/UpdateCharacterAttributeRequest.php",
    "content": "<?php\n\nnamespace App\\Http\\Requests;\n\nuse Illuminate\\Foundation\\Http\\FormRequest;\n\nclass UpdateCharacterAttributeRequest extends FormRequest\n{\n    /**\n     * Determine if the user is authorized to make this request.\n     *\n     * @return bool\n     */\n    public function authorize()\n    {\n        return true;\n    }\n\n    /**\n     * Get the validation rules that apply to the request.\n     *\n     * @return array\n     */\n    public function rules()\n    {\n        return [\n            'attribute' => 'required|in:strength,agility,constitution,intelligence,charisma',\n        ];\n    }\n}\n"
  },
  {
    "path": "app/Http/Requests/UploadImageRequest.php",
    "content": "<?php\n\nnamespace App\\Http\\Requests;\n\nuse Illuminate\\Foundation\\Http\\FormRequest;\n\nclass UploadImageRequest extends FormRequest\n{\n    public function authorize()\n    {\n        return true;\n    }\n\n    /**\n     * Get the validation rules that apply to the request.\n     *\n     * @return array\n     */\n    public function rules()\n    {\n        return [\n            'file' => [\n                'required',\n                'image',\n                'mimes:jpeg,png,gif',\n                'max:' . bytes_to_kilobytes(config('filesystems.max_size_in_bytes'))\n            ],\n        ];\n    }\n}\n"
  },
  {
    "path": "app/Http/ViewComposers/BattlesComposer.php",
    "content": "<?php\n\nnamespace App\\Http\\ViewComposers;\n\nuse App\\Models\\Battle;\nuse App\\Models\\Character;\nuse Illuminate\\Database\\Eloquent\\Builder;\nuse Illuminate\\Database\\Eloquent\\Collection;\nuse Illuminate\\Support\\Arr;\nuse Illuminate\\View\\View;\n\nclass BattlesComposer\n{\n    /**\n     * Bind data to the view.\n     *\n     * @param  View $view\n     * @return void\n     */\n    public function compose(View $view)\n    {\n        $data = $view->getData();\n\n        /** @var Character $character */\n        $character = Arr::get($data, 'character');\n\n        /** @var Collection $battles */\n        $battles = Battle::query()->where(function (Builder $query) use ($character) {\n            $query->where([\n                'attacker_id' => $character->id,\n            ]);\n        })->orWhere(function (Builder $query) use ($character) {\n            $query->where([\n                'defender_id' => $character->id,\n            ]);\n        })->orderByDesc('created_at')->paginate(10);\n\n        $unseenBattles = $character->defends()->unseenByDefender()->whereIn('id', $battles->pluck('id'));\n\n        $unseenBattles->markAsSeenByDefender();\n\n        $view->with(compact('character', 'battles'));\n    }\n}\n"
  },
  {
    "path": "app/Http/ViewComposers/CharacterGeneralInfoComposer.php",
    "content": "<?php\n\nnamespace App\\Http\\ViewComposers;\n\nuse App\\Models\\Character;\nuse App\\Modules\\Level\\Application\\Services\\LevelService;\nuse Illuminate\\Support\\Arr;\nuse Illuminate\\View\\View;\n\nclass CharacterGeneralInfoComposer\n{\n    /**\n     * @var LevelService\n     */\n    private $levelService;\n\n    public function __construct(LevelService $levelService)\n    {\n        $this->levelService = $levelService;\n    }\n\n    /**\n     * Bind data to the view.\n     *\n     * @param  View $view\n     * @return void\n     */\n    public function compose(View $view)\n    {\n        $data = $view->getData();\n\n        /** @var Character $character */\n        $character = Arr::get($data, 'character');\n\n        $level = $this->levelService->getLevel($character->getLevelNumber());\n\n        $view->with(compact('character', 'level'));\n    }\n}\n"
  },
  {
    "path": "app/Http/ViewComposers/CharacterMessagesComposer.php",
    "content": "<?php\n\nnamespace App\\Http\\ViewComposers;\n\nuse App\\Models\\Character;\nuse App\\Models\\Message;\nuse Illuminate\\Database\\Eloquent\\Builder;\nuse Illuminate\\Support\\Arr;\nuse Illuminate\\Support\\Facades\\Auth;\nuse Illuminate\\View\\View;\n\nclass CharacterMessagesComposer\n{\n    /**\n     * Bind data to the view.\n     *\n     * @param  View $view\n     * @return void\n     */\n    public function compose(View $view)\n    {\n        $data = $view->getData();\n\n        /** @var Character $currentCharacter */\n        /** @var Character $otherCharacter */\n        $currentCharacter = Auth::user()->character;\n        $otherCharacter = Arr::get($data, 'character');\n\n        $messages = Message::query()->where(function (Builder $query) use ($currentCharacter, $otherCharacter) {\n            $query->where([\n                'to_id' => $currentCharacter->id,\n                'from_id' => $otherCharacter->id,\n            ]);\n        })->orWhere(function (Builder $query) use ($currentCharacter, $otherCharacter) {\n            $query->where([\n                'to_id' => $otherCharacter->id,\n                'from_id' => $currentCharacter->id,\n            ]);\n        })->orderByDesc('created_at')->paginate(5);\n\n        $otherCharacter->sentMessages()->whereIn('id', $messages->pluck('id'))->markAsRead();\n\n        $contentLimit = Message::CONTENT_LIMIT;\n\n        $view->with(compact('messages', 'currentCharacter', 'otherCharacter', 'contentLimit'));\n    }\n}\n"
  },
  {
    "path": "app/Http/ViewComposers/MessagesComposer.php",
    "content": "<?php\n\nnamespace App\\Http\\ViewComposers;\n\nuse App\\Models\\Character;\nuse App\\Models\\Message;\nuse Illuminate\\Database\\Query\\Builder;\nuse Illuminate\\Support\\Facades\\Auth;\nuse Illuminate\\Support\\Facades\\DB;\nuse Illuminate\\View\\View;\n\nclass MessagesComposer\n{\n    /**\n     * Bind data to the view.\n     *\n     * @param  View $view\n     * @return void\n     */\n    public function compose(View $view)\n    {\n        /** @var Character $currentCharacter */\n        $currentCharacter = Auth::user()->character;\n\n        $builder = Message::query()->whereIn('auto_id', function (Builder $query) use ($currentCharacter)       {\n            $query\n                ->select(DB::raw('max(`auto_id`)'))\n                ->from('messages')\n                ->where(function (Builder $query) use ($currentCharacter) {\n                $query->where([\n                    'to_id' => $currentCharacter->id,\n                ]);\n            })->orWhere(function (Builder $query) use ($currentCharacter) {\n                $query->where([\n                    'from_id' => $currentCharacter->id,\n                ]);\n            })->groupBy(DB::raw('\n                CASE WHEN from_id = \"' . $currentCharacter->id . '\"\n                  THEN to_id\n                  ELSE from_id\n                END'));\n        })->orderByDesc('auto_id');\n\n        $messages = $builder->paginate(5);\n\n        $view->with(compact('messages', 'currentCharacter'));\n    }\n}"
  },
  {
    "path": "app/Models/Battle.php",
    "content": "<?php\n\nnamespace App\\Models;\n\nuse App\\Traits\\UsesStringId;\nuse Illuminate\\Database\\Eloquent\\Collection;\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Illuminate\\Database\\Eloquent\\Relations\\BelongsTo;\nuse Illuminate\\Database\\Eloquent\\Relations\\HasMany;\n\n/**\n * @property Collection rounds\n * @property Character attacker\n * @property Character defender\n * @property int victor_xp_gained\n * @property Location location\n * @property Character victor\n */\nclass Battle extends Model\n{\n    use UsesStringId;\n\n    protected $guarded = [];\n\n    public function rounds(): HasMany\n    {\n        return $this->hasMany(BattleRound::class);\n    }\n\n    public function attacker(): BelongsTo\n    {\n        return $this->belongsTo(Character::class, 'attacker_id');\n    }\n\n    public function defender(): BelongsTo\n    {\n        return $this->belongsTo(Character::class, 'defender_id');\n    }\n\n    public function victor(): BelongsTo\n    {\n        return $this->belongsTo(Character::class, 'victor_id');\n    }\n\n    public function location(): BelongsTo\n    {\n        return $this->belongsTo(Location::class);\n    }\n\n    /**\n     * @param $query\n     * @return mixed\n     */\n    public function scopeUnseenByDefender($query)\n    {\n        return $query->where('seen_by_defender', false);\n    }\n\n    /**\n     * Read the selected Messages\n     *\n     * @param $query\n     * @return mixed\n     */\n    public function scopeMarkAsSeenByDefender($query)\n    {\n        return $query->update(['seen_by_defender' => true]);\n    }\n\n    public function getAttacker(): Character\n    {\n        return $this->attacker;\n    }\n\n    public function getDefender(): Character\n    {\n        return $this->defender;\n    }\n\n    public function isTheVictor(Character $character): bool\n    {\n        return $this->victor->id ===  $character->getId();\n    }\n}\n"
  },
  {
    "path": "app/Models/BattleRound.php",
    "content": "<?php\n\nnamespace App\\Models;\n\nuse App\\Traits\\UsesStringId;\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Illuminate\\Database\\Eloquent\\Relations\\HasMany;\n\nclass BattleRound extends Model\n{\n    use UsesStringId;\n\n    protected $guarded = [];\n\n    /**\n     * @return HasMany\n     */\n    public function turns()\n    {\n        return $this->hasMany(BattleTurn::class);\n    }\n}\n"
  },
  {
    "path": "app/Models/BattleTurn.php",
    "content": "<?php\n\nnamespace App\\Models;\n\nuse App\\Traits\\UsesStringId;\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Illuminate\\Database\\Eloquent\\Relations\\BelongsTo;\n\nclass BattleTurn extends Model\n{\n    use UsesStringId;\n\n    protected $guarded = [];\n\n    /**\n     * @return BelongsTo\n     */\n    public function executor()\n    {\n        return $this->belongsTo(Character::class, 'executor_id');\n    }\n    /**\n     * @return BelongsTo\n     */\n    public function target()\n    {\n        return $this->belongsTo(Character::class, 'target_id');\n    }\n}\n"
  },
  {
    "path": "app/Models/Character.php",
    "content": "<?php\n\nnamespace App\\Models;\n\nuse App\\Modules\\Character\\Domain\\CharacterType;\nuse App\\Modules\\Equipment\\Domain\\ItemStatus;\nuse App\\Modules\\Equipment\\Domain\\ItemType;\nuse App\\Traits\\UsesStringId;\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Illuminate\\Database\\Eloquent\\Relations\\BelongsTo;\nuse Illuminate\\Database\\Eloquent\\Relations\\HasMany;\nuse Illuminate\\Database\\Eloquent\\Relations\\HasOne;\n\n/**\n * @property User user\n * @property Location location\n * @property string id\n * @property integer hit_points\n * @property integer xp\n * @property integer available_attribute_points\n * @property integer battles_won\n * @property integer battles_lost\n * @property integer strength\n * @property integer agility\n * @property integer constitution\n * @property integer intelligence\n * @property integer charisma\n * @property string location_id\n * @property Race race\n * @property string gender\n * @property string type\n * @property int total_hit_points\n * @property int victor_xp_gained\n * @property Image profilePicture\n * @property string name\n * @property int level_id\n * @property string profile_picture_id\n * @property Inventory inventory\n * @property Store store\n * @property integer reputation\n */\nclass Character extends Model\n{\n    use UsesStringId;\n\n    protected $guarded = [];\n\n    public function user(): BelongsTo\n    {\n        return $this->belongsTo(User::class);\n    }\n\n    public function race(): BelongsTo\n    {\n        return $this->belongsTo(Race::class);\n    }\n\n    public function location(): BelongsTo\n    {\n        return $this->belongsTo(Location::class);\n    }\n\n    public function profilePicture(): BelongsTo\n    {\n        return $this->belongsTo(Image::class, 'profile_picture_id');\n    }\n\n    public function images(): HasMany\n    {\n        return $this->hasMany(Image::class);\n    }\n\n    public function inventory(): HasOne\n    {\n        return $this->hasOne(Inventory::class);\n    }\n\n    public function store(): HasOne\n    {\n        return $this->hasOne(Store::class);\n    }\n\n    public function receivedMessages(): HasMany\n    {\n        return $this->hasMany(Message::class, 'to_id');\n    }\n\n    public function sentMessages(): HasMany\n    {\n        return $this->hasMany(Message::class, 'from_id');\n    }\n\n    public function attacks(): HasMany\n    {\n        return $this->hasMany(Battle::class, 'attacker_id');\n    }\n\n    public function defends(): HasMany\n    {\n        return $this->hasMany(Battle::class, 'defender_id');\n    }\n\n    public function battles(): HasMany\n    {\n        return $this->hasMany(Battle::class, 'defender_id');\n    }\n\n    public function sendMessageTo(Character $companion, string $content): Character\n    {\n        $this->sentMessages()->create([\n            'to_id' => $companion->getId(),\n            'content' => $content,\n        ]);\n\n        return $this;\n    }\n\n    public function isYou(): bool\n    {\n        return $this->isPlayerCharacter() && $this->user->isCurrentAuthenticatedUser();\n    }\n\n    public function isOwnMerchant(): bool\n    {\n        return $this->isMerchant() && $this->user->isCurrentAuthenticatedUser();\n    }\n\n    public function isPlayerCharacter(): bool\n    {\n        return $this->type === CharacterType::PLAYER;\n    }\n\n    public function isMerchant(): bool\n    {\n        return $this->type === CharacterType::MERCHANT;\n    }\n\n    public function isMonster(): bool\n    {\n        return $this->type === CharacterType::MONSTER;\n    }\n\n    public function isNPC(): bool\n    {\n        return !$this->isPlayerCharacter();\n    }\n\n    public function hasProfilePicture(): bool\n    {\n        return $this->profilePicture()->exists();\n    }\n\n    public function isOnline(): bool\n    {\n        if($this->isNPC()) {\n            return true;\n        }\n\n        return $this->user->isOnline();\n    }\n\n    public function getProfilePicture(): Image\n    {\n        return $this->profilePicture;\n    }\n\n    public function getProfilePictureFull(): string\n    {\n        if ($this->profilePicture()->exists())\n        {\n            /** @var Image $image */\n            $image = $this->profilePicture()->first();\n\n            return $image->getFilePathFull();\n        }\n\n        return $this->race->getImageByGender($this->gender);\n    }\n\n    public function getProfilePictureSmall(): string\n    {\n        if ($this->profilePicture()->exists())\n        {\n            /** @var Image $image */\n            $image = $this->profilePicture()->first();\n\n            return $image->getFilePathSmall();\n        }\n\n        return 'svg/avatar.svg';\n    }\n\n    public function getProfilePictureId(): ?string\n    {\n        return $this->profile_picture_id;\n    }\n\n    public function getRaceName(): string\n    {\n        return $this->race->getName();\n    }\n\n    public function getLevelNumber():int\n    {\n        return $this->level_id;\n    }\n\n    public function getLocationName():string\n    {\n        return $this->location->getName();\n    }\n\n    public function getId(): string\n    {\n        return $this->id;\n    }\n\n    public function isAlive(): bool\n    {\n        return $this->hit_points > 0;\n    }\n\n    public function getStrength(): int\n    {\n        return $this->strength;\n    }\n\n    public function getAgility(): int\n    {\n        return $this->agility;\n    }\n\n    public function getConstitution(): int\n    {\n        return $this->constitution;\n    }\n\n    public function getIntelligence(): int\n    {\n        return $this->intelligence;\n    }\n\n    public function getCharisma(): int\n    {\n        return $this->charisma;\n    }\n\n    public function getLocationId(): string\n    {\n        return $this->location_id;\n    }\n\n    public function getHitPoints(): int\n    {\n        return $this->hit_points;\n    }\n\n    public function getTotalHitPoints(): int\n    {\n        return $this->total_hit_points;\n    }\n\n    public function getUserId()\n    {\n        return $this->user ? $this->user->getId() : null;\n    }\n\n    public function getName(): string\n    {\n        return $this->name;\n    }\n\n    public function getGender(): string\n    {\n        return $this->gender;\n    }\n\n    public function getType(): string\n    {\n        return $this->type;\n    }\n\n    public function getRaceId(): int\n    {\n        return $this->race->getId();\n    }\n\n    public function getXp(): int\n    {\n        return $this->xp;\n    }\n\n    public function getAvailableAttributePoints(): int\n    {\n        return $this->available_attribute_points;\n    }\n\n    public function getBattlesLost(): int\n    {\n        return $this->battles_lost;\n    }\n\n    public function getBattlesWon(): int\n    {\n        return $this->battles_won;\n    }\n\n    public function getHeadGearItem()\n    {\n        return $this->inventory->items()\n            ->where('type', ItemType::HEAD_GEAR)\n            ->wherePivot('status', ItemStatus::EQUIPPED)\n            ->first()\n        ;\n    }\n\n    public function getBodyArmorItem()\n    {\n        return $this->inventory->items()\n            ->where('type', ItemType::BODY_ARMOR)\n            ->wherePivot('status', ItemStatus::EQUIPPED)\n            ->first()\n        ;\n    }\n\n    public function getMainHandItem()\n    {\n        return $this->inventory->items()\n            ->where('type', ItemType::MAIN_HAND)\n            ->wherePivot('status', ItemStatus::EQUIPPED)\n            ->first()\n        ;\n    }\n\n    public function getOffHandItem()\n    {\n        return $this->inventory->items()\n            ->where('type', ItemType::OFF_HAND)\n            ->wherePivot('status', ItemStatus::EQUIPPED)\n            ->first()\n        ;\n    }\n}\n"
  },
  {
    "path": "app/Models/Image.php",
    "content": "<?php\n\nnamespace App\\Models;\n\nuse App\\Traits\\UsesStringId;\nuse Illuminate\\Database\\Eloquent\\Model;\n\n/**\n * @property string file_path_full\n * @property string file_path_small\n * @property string file_path_icon\n * @property string id\n * @property string character_id\n */\nclass Image extends Model\n{\n    use UsesStringId;\n\n    protected $guarded = [];\n\n    public function getId()\n    {\n        return $this->id;\n    }\n\n    public function getCharacterId(): string\n    {\n        return $this->character_id;\n    }\n\n    public function getFilePathFull(): string\n    {\n        return $this->file_path_full;\n    }\n\n    public function getFilePathSmall(): string\n    {\n        return $this->file_path_small;\n    }\n\n    public function getFilePathIcon(): string\n    {\n        return $this->file_path_icon;\n    }\n}\n"
  },
  {
    "path": "app/Models/Inventory.php",
    "content": "<?php\n\nnamespace App\\Models;\n\nuse App\\Traits\\UsesStringId;\nuse Illuminate\\Database\\Eloquent\\Collection;\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Illuminate\\Database\\Eloquent\\Relations\\BelongsTo;\nuse Illuminate\\Database\\Eloquent\\Relations\\BelongsToMany;\n\n/**\n * @property Character character\n * @property Collection items\n * @property string id\n * @property string character_id\n * @property int money\n */\nclass Inventory extends Model\n{\n    use UsesStringId;\n\n    protected $casts = [\n        'money' => 'integer',\n    ];\n\n    protected $guarded = [];\n\n    public function character(): BelongsTo\n    {\n        return $this->belongsTo(Character::class, 'character_id');\n    }\n\n    public function items(): BelongsToMany\n    {\n        return $this->belongsToMany(Item::class)->withPivot('inventory_slot_number', 'status');\n    }\n\n    public function getId(): string\n    {\n        return $this->id;\n    }\n\n    public function getCharacterId(): string\n    {\n        return $this->character_id;\n    }\n\n    public function getMoney(): int\n    {\n        return $this->money;\n    }\n}\n"
  },
  {
    "path": "app/Models/Item.php",
    "content": "<?php\n\nnamespace App\\Models;\n\nuse App\\Modules\\Equipment\\Domain\\ItemStatus;\nuse App\\Traits\\UsesStringId;\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Illuminate\\Database\\Eloquent\\Relations\\BelongsTo;\nuse Illuminate\\Database\\Eloquent\\Relations\\BelongsToMany;\n\n/**\n * @property string id\n * @property string name\n * @property string $description\n * @property string image_file_path\n * @property string type\n * @property string status\n * @property array effects\n * @property string prototype_id\n * @property string creator_character_id\n * @property string owner_character_id\n * @property int inventory_slot_number\n * @property int price\n * @property Inventory inventory\n * @property mixed pivot\n */\nclass Item extends Model\n{\n    use UsesStringId;\n\n    protected $guarded = [];\n\n    protected $casts = [\n        'effects' => 'array'\n    ];\n\n    public function inventory(): BelongsToMany\n    {\n        return $this->belongsToMany(Inventory::class);\n    }\n\n    public function prototype(): BelongsTo\n    {\n        return $this->belongsTo(ItemPrototype::class);\n    }\n\n    public function getId(): string\n    {\n        return $this->id;\n    }\n\n    public function getName(): string\n    {\n        return $this->name;\n    }\n\n    public function getDescription(): string\n    {\n        return $this->description;\n    }\n\n    public function getImageFilePath(): string\n    {\n        return $this->image_file_path;\n    }\n\n    public function getType(): string\n    {\n        return $this->type;\n    }\n\n    public function getStatus(): string\n    {\n        return $this->status;\n    }\n\n    public function getEffects(): array\n    {\n        return $this->effects;\n    }\n\n    public function getPrice(): int\n    {\n        return $this->price;\n    }\n\n    public function getPrototypeId(): string\n    {\n        return $this->prototype_id;\n    }\n\n    public function getCreatorCharacterId(): string\n    {\n        return $this->creator_character_id;\n    }\n\n    public function isEquipped(): bool\n    {\n        return $this->pivot->status === ItemStatus::EQUIPPED;\n    }\n\n    public function getInventorySlotNumber(): int\n    {\n        return $this->pivot->inventory_slot_number;\n    }\n}\n"
  },
  {
    "path": "app/Models/ItemPrototype.php",
    "content": "<?php\n\nnamespace App\\Models;\n\nuse App\\Traits\\UsesStringId;\nuse Illuminate\\Database\\Eloquent\\Model;\n\n/**\n * @property string id\n * @property string name\n * @property string $description\n * @property string image_file_path\n * @property string type\n * @property array effects\n * @property int price\n */\nclass ItemPrototype extends Model\n{\n    use UsesStringId;\n\n    protected $guarded = [];\n\n    protected $casts = [\n        'effects' => 'array'\n    ];\n\n    public function getId(): string\n    {\n        return $this->id;\n    }\n\n    public function getName(): string\n    {\n        return $this->name;\n    }\n\n    public function getDescription(): string\n    {\n        return $this->description;\n    }\n\n    public function getImageFilePath(): string\n    {\n        return $this->image_file_path;\n    }\n\n    public function getType(): string\n    {\n        return $this->type;\n    }\n\n    public function getEffects(): array\n    {\n        return $this->effects;\n    }\n\n    public function getPrice(): int\n    {\n        return $this->price;\n    }\n}\n"
  },
  {
    "path": "app/Models/Location.php",
    "content": "<?php\n\nnamespace App\\Models;\n\nuse App\\Traits\\UsesStringId;\nuse Carbon\\Carbon;\nuse Illuminate\\Database\\Eloquent\\Collection;\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Illuminate\\Database\\Eloquent\\Relations\\BelongsToMany;\nuse Illuminate\\Database\\Eloquent\\Relations\\HasMany;\n\n/**\n * @property string id\n * @property string name\n * @property Collection adjacentLocations\n */\nclass Location extends Model\n{\n    use UsesStringId;\n\n    static protected $oppositeDirections = [\n        'north' => 'south',\n        'east' => 'west',\n    ];\n\n    /**\n     * Getting all possible movement directions.\n     *\n     * @return array\n     */\n    static public function getDirections()\n    {\n        return array_merge(array_keys(Location::$oppositeDirections), array_values(Location::$oppositeDirections));\n    }\n\n    /**\n     * Getting the opposite direction\n     *\n     * @param $direction\n     *\n     * @return mixed\n     */\n    static protected function getAppositeDirection($direction)\n    {\n        if (array_key_exists ($direction, self::$oppositeDirections)) {\n            return self::$oppositeDirections[$direction];\n        }\n\n        if (in_array($direction, self::$oppositeDirections)) {\n            return array_search($direction, self::$oppositeDirections);\n        }\n\n        throw new \\InvalidArgumentException('Invalid direction: '.$direction);\n    }\n\n    /**\n     * @param $direction\n     *\n     * @return bool\n     */\n    static protected function isValidDirection($direction)\n    {\n        return array_key_exists ($direction, self::$oppositeDirections) || in_array($direction, self::$oppositeDirections);\n    }\n\n    /**\n     * Get the characters at the location.\n     *\n     * @return HasMany\n     */\n    public function characters()\n    {\n        return $this->hasMany(Character::class);\n    }\n\n    /**\n     * @return BelongsToMany\n     */\n    public function adjacentLocations()\n    {\n        return $this->belongsToMany(Location::class, 'adjacent_location', 'location_id', 'adjacent_location_id')->withPivot('direction');\n    }\n\n    public function adjacent($type)\n    {\n        return $this->adjacentLocations->filter(function (Location $value, $key) use ($type) {\n            return $value->getOriginal('pivot_direction') === $type;\n        })->first();\n    }\n\n    public function addAdjacentLocation(Location $adjacent, $direction)\n    {\n        if (!self::isValidDirection($direction)) {\n            throw new \\InvalidArgumentException('Invalid adjacent direction type: '.$direction);\n        }\n\n        $this->adjacentLocations()->attach($adjacent, [\n            'direction' => $direction,\n            \"created_at\"            => Carbon::now(),\n            \"updated_at\"            => Carbon::now(),\n        ]); // add adjacent\n\n        $adjacent->adjacentLocations()->attach($this, [\n            'direction' => self::getAppositeDirection($direction),\n            \"created_at\"            => Carbon::now(),\n            \"updated_at\"            => Carbon::now(),\n        ]); // add yourself, too\n    }\n\n    public function removeAdjacentLocation(Location $adjacent)\n    {\n        $this->adjacentLocations()->detach($adjacent);   // remove friend\n        $adjacent->adjacentLocations()->detach($this);  // remove yourself, too\n    }\n\n    public function getName(): string\n    {\n        return $this->name;\n    }\n\n    public function isAdjacentLocation(Location $location): bool\n    {\n        return (bool)$this->adjacentLocations()->where('id', $location->getId())->first();\n    }\n\n    public function getId(): string\n    {\n        return $this->id;\n    }\n}\n"
  },
  {
    "path": "app/Models/Message.php",
    "content": "<?php\n\nnamespace App\\Models;\n\nuse App\\Traits\\UsesStringId;\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Illuminate\\Database\\Eloquent\\Relations\\BelongsTo;\nuse Illuminate\\Support\\Str;\n\n/**\n * @property string state\n * @property string from_id\n * @property string to_id\n * @property string content\n * @property string id\n */\nclass Message extends Model\n{\n    use UsesStringId;\n\n    const UNREAD = 'unread';\n    const READ = 'read';\n\n    const CONTENT_LIMIT = 500;\n\n    protected $guarded = [];\n\n    public $timestamps = true;\n\n    /**\n     * @return BelongsTo\n     */\n    public function sender()\n    {\n        return $this->belongsTo(Character::class, 'from_id');\n    }\n\n    /**\n     * @return BelongsTo\n     */\n    public function recipient()\n    {\n        return $this->belongsTo(Character::class, 'to_id');\n    }\n\n    /**\n     * Get the number of new messages related to this conversation\n     *\n     * @param $query\n     * @return mixed\n     */\n    public function scopeUnread($query)\n    {\n        return $query->where('state', Message::UNREAD);\n    }\n\n    /**\n     * Read the selected Messages\n     *\n     * @param $query\n     * @return mixed\n     */\n    public function scopeMarkAsRead($query)\n    {\n        return $query->update(['state' => Message::READ]);\n    }\n\n    /**\n     * Set the user's first name.\n     *\n     * @param  string  $value\n     * @return void\n     */\n    public function setContentAttribute($value)\n    {\n        $value = str_replace(\"\\r\\n\", \"\\n\", $value);\n\n        $limitedString = Str::limit($value, self::CONTENT_LIMIT, '');\n\n        $this->attributes['content'] = nl2br(e($limitedString));\n    }\n\n    public function unseenByRecipient(): bool\n    {\n        return (string)$this->getOriginal('state') === self::UNREAD;\n    }\n}\n"
  },
  {
    "path": "app/Models/Race.php",
    "content": "<?php\n\nnamespace App\\Models;\n\nuse Illuminate\\Database\\Eloquent\\Model;\n\n/**\n * @property string name\n * @property string description\n * @property string male_image\n * @property string female_image\n */\nclass Race extends Model\n{\n    const ATTRIBUTE_STRENGTH = 'strength';\n    const ATTRIBUTE_AGILITY = 'agility';\n    const ATTRIBUTE_CONSTITUTION = 'constitution';\n    const ATTRIBUTE_INTELLIGENCE = 'intelligence';\n    const ATTRIBUTE_CHARISMA = 'charisma';\n\n    const ATTRIBUTE_STARTING_LOCATION_ID = 'starting_location_id';\n    const ATTRIBUTE_NAME = 'name';\n\n    public function getImageByGender(string $gender): string\n    {\n        return $this->{\"{$gender}_image\"};\n    }\n\n    public function getId(): int\n    {\n        return $this->getKey();\n    }\n\n    public function getStartingLocationId(): string\n    {\n        return $this->{self::ATTRIBUTE_STARTING_LOCATION_ID};\n    }\n\n    public function getStrength(): int\n    {\n        return $this->{self::ATTRIBUTE_STRENGTH};\n    }\n\n    public function getAgility(): int\n    {\n        return $this->{self::ATTRIBUTE_AGILITY};\n    }\n\n    public function getConstitution(): int\n    {\n        return $this->{self::ATTRIBUTE_CONSTITUTION};\n    }\n\n    public function getIntelligence(): int\n    {\n        return $this->{self::ATTRIBUTE_INTELLIGENCE};\n    }\n\n    public function getCharisma(): int\n    {\n        return $this->{self::ATTRIBUTE_CHARISMA};\n    }\n\n    public function getName(): string\n    {\n        return $this->name;\n    }\n\n    public function getDescription(): string\n    {\n        return $this->description;\n    }\n\n    public function getMaleImage(): string\n    {\n        return $this->male_image;\n    }\n\n    public function getFemaleImage(): string\n    {\n        return $this->female_image;\n    }\n}\n"
  },
  {
    "path": "app/Models/Store.php",
    "content": "<?php\n\nnamespace App\\Models;\n\nuse App\\Traits\\UsesStringId;\nuse Illuminate\\Database\\Eloquent\\Collection;\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Illuminate\\Database\\Eloquent\\Relations\\BelongsTo;\nuse Illuminate\\Database\\Eloquent\\Relations\\BelongsToMany;\n\n/**\n * @property Character character\n * @property Collection items\n * @property string id\n * @property string type\n * @property string character_id\n * @property int money\n */\nclass Store extends Model\n{\n    use UsesStringId;\n\n    protected $casts = [\n        'money' => 'integer',\n    ];\n\n    protected $guarded = [];\n\n    public function character(): BelongsTo\n    {\n        return $this->belongsTo(Character::class, 'character_id');\n    }\n\n    public function items(): BelongsToMany\n    {\n        return $this->belongsToMany(Item::class, 'store_item')\n            ->withPivot('inventory_slot_number', 'price');\n    }\n\n    public function getId(): string\n    {\n        return $this->id;\n    }\n\n    public function getType(): string\n    {\n        return $this->type;\n    }\n\n    public function getCharacterId(): string\n    {\n        return $this->character_id;\n    }\n\n    public function getMoney(): int\n    {\n        return $this->money;\n    }\n}\n"
  },
  {
    "path": "app/Models/User.php",
    "content": "<?php\n\nnamespace App\\Models;\n\nuse Carbon\\Carbon;\nuse Illuminate\\Database\\Eloquent\\Factories\\HasFactory;\nuse Illuminate\\Database\\Eloquent\\Relations\\HasOne;\nuse Illuminate\\Notifications\\Notifiable;\nuse Illuminate\\Support\\Facades\\Auth;\nuse Illuminate\\Support\\Facades\\Cache;\n\n/**\n * @property Character character\n * @property integer id\n */\nclass User extends \\TCG\\Voyager\\Models\\User\n{\n    use HasFactory, Notifiable;\n\n    /**\n     * The attributes that are mass assignable.\n     *\n     * @var array\n     */\n    protected $fillable = [\n        'name',\n        'email',\n        'password',\n    ];\n\n    /**\n     * The attributes that should be hidden for arrays.\n     *\n     * @var array\n     */\n    protected $hidden = [\n        'password',\n        'remember_token',\n    ];\n\n    /**\n     * The attributes that should be cast to native types.\n     *\n     * @var array\n     */\n    protected $casts = [\n        'email_verified_at' => 'datetime',\n    ];\n    public function character(): HasOne\n    {\n        return $this->hasOne(Character::class);\n    }\n\n    public function hasCharacter(): bool\n    {\n        return $this->character()->getQuery()->exists();\n    }\n\n    public function getId(): int\n    {\n        return $this->id;\n    }\n\n    public function isCurrentAuthenticatedUser(): bool\n    {\n        return $this->getId() == Auth::id();\n    }\n\n    public function getCharacter(): Character\n    {\n        return $this->character;\n    }\n\n    public function hasThisCharacter(Character $character): bool\n    {\n        return $this->character->id === $character->getId();\n    }\n\n    public function updateLastUserActivity(): User\n    {\n        $expiresAt = Carbon::now()->addMinutes(5);\n\n        Cache::put('last-user-activity-' . $this->id, true, $expiresAt);\n\n        return $this;\n    }\n\n    public function isOnline(): bool\n    {\n        return Cache::has('last-user-activity-' . $this->id);\n    }\n}"
  },
  {
    "path": "app/Modules/Battle/Application/Contracts/BattleRepositoryInterface.php",
    "content": "<?php\n\nnamespace App\\Modules\\Battle\\Application\\Contracts;\n\nuse App\\Modules\\Battle\\Domain\\Battle;\nuse App\\Modules\\Battle\\Domain\\BattleId;\n\ninterface BattleRepositoryInterface\n{\n    public function nextIdentity(): BattleId;\n\n    public function add(Battle $battle):void;\n}\n"
  },
  {
    "path": "app/Modules/Battle/Domain/Battle.php",
    "content": "<?php\n\nnamespace App\\Modules\\Battle\\Domain;\n\nuse App\\Modules\\Character\\Domain\\Character;\nuse App\\Traits\\GeneratesUuid;\n\nclass Battle\n{\n    use GeneratesUuid;\n\n    /**\n     * @var BattleId\n     */\n    private $id;\n\n    /**\n     * @var string\n     */\n    private $locationId;\n\n    /**\n     * @var Character\n     */\n    private $attacker;\n\n    /**\n     * @var Character\n     */\n    private $defender;\n\n    /**\n     * @var BattleRounds\n     */\n    private $rounds;\n\n    /**\n     * @var int\n     */\n    private $victorXpGained;\n\n    /**\n     * @var Character|null\n     */\n    private $victor;\n\n    public function __construct(\n        BattleId $id,\n        string $locationId,\n        Character $attacker,\n        Character $defender,\n        BattleRounds $rounds,\n        int $victorXpGained,\n        Character $victor = null\n    )\n    {\n        $this->id = $id;\n        $this->locationId = $locationId;\n        $this->attacker = $attacker;\n        $this->defender = $defender;\n        $this->rounds = $rounds;\n        $this->victorXpGained = $victorXpGained;\n        $this->victor = $victor;\n    }\n\n    public function execute(): void\n    {\n        do {\n            $round = $this->createRound(\n                $this->getAttacker(),\n                $this->getDefender()\n            );\n\n            $round->execute();\n\n            $this->rounds->push($round);\n\n        } while ($round->notLastRound());\n\n        $this->victor = $this->attacker->isAlive() ? $this->attacker : $this->defender;\n        $loser = $this->attacker->isAlive() ? $this->defender : $this->attacker;\n\n        $this->victorXpGained = $this->calculateVictorXpGained($loser, $this->victor);\n    }\n\n    private function calculateVictorXpGained(Character $loser, Character $victor): int\n    {\n        return max($loser->getLevelNumber() - $victor->getLevelNumber(), 1) * 3;\n    }\n\n    public function getId(): BattleId\n    {\n        return $this->id;\n    }\n\n    public function getAttacker(): Character\n    {\n        return $this->attacker;\n    }\n\n    public function getDefender(): Character\n    {\n        return $this->defender;\n    }\n\n    public function getVictorXpGained(): int\n    {\n        return $this->victorXpGained;\n    }\n\n    public function getRounds(): BattleRounds\n    {\n        return $this->rounds;\n    }\n\n    public function getVictor(): Character\n    {\n        return $this->victor;\n    }\n\n    public function getLoser(): Character\n    {\n        return $this->victor->equals($this->attacker) ? $this->defender : $this->attacker;\n    }\n\n    public function getLocationId(): string\n    {\n        return $this->locationId;\n    }\n\n    private function createRound(Character $attacker, Character $defender): BattleRound\n    {\n        return new BattleRound(\n            $this->generateUuid(),\n            $attacker,\n            $defender,\n            new BattleTurns()\n        );\n    }\n}\n"
  },
  {
    "path": "app/Modules/Battle/Domain/BattleId.php",
    "content": "<?php declare(strict_types=1);\n\n\nnamespace App\\Modules\\Battle\\Domain;\n\n\nuse App\\Modules\\Generic\\Domain\\BaseId;\n\nclass BattleId extends BaseId\n{\n}\n"
  },
  {
    "path": "app/Modules/Battle/Domain/BattleRound.php",
    "content": "<?php\n\n\nnamespace App\\Modules\\Battle\\Domain;\n\nuse App\\Modules\\Character\\Domain\\Character;\nuse App\\Traits\\GeneratesUuid;\n\nclass BattleRound\n{\n    use GeneratesUuid;\n\n    /**\n     * @var string\n     */\n    private $id;\n\n    /**\n     * @var Character\n     */\n    private $attacker;\n\n    /**\n     * @var Character\n     */\n    private $defender;\n\n    /**\n     * @var BattleTurns\n     */\n    private $turns;\n\n    public function __construct(\n        string $id,\n        Character $attacker,\n        Character $defender,\n        BattleTurns $turns\n    ) {\n        $this->id = $id;\n        $this->attacker = $attacker;\n        $this->defender = $defender;\n        $this->turns = $turns;\n    }\n\n    public function getId(): string\n    {\n        return $this->id;\n    }\n\n    public function getTurns(): BattleTurns\n    {\n        return $this->turns;\n    }\n\n    public function execute(): void\n    {\n        $turn = $this->createTurn($this->attacker, $this->defender);\n\n        $turn->execute();\n\n        $this->turns->push($turn);\n\n        if ($turn->isTargetAlive()) {\n\n            $turn = $this->createTurn($this->defender, $this->attacker);\n\n            $turn->execute();\n\n            $this->turns->push($turn);\n        }\n    }\n\n    public function notLastRound(): bool\n    {\n        /** @var BattleTurn $lastTurn */\n        $lastTurn = $this->turns->last();\n\n        return $lastTurn->isTargetAlive();\n    }\n\n    private function createTurn(Character $owner, Character $target): BattleTurn\n    {\n        return new BattleTurn(\n            $this->generateUuid(),\n            $owner,\n            $target,\n            BattleTurnResult::none()\n        );\n    }\n}\n"
  },
  {
    "path": "app/Modules/Battle/Domain/BattleRounds.php",
    "content": "<?php\n\n\nnamespace App\\Modules\\Battle\\Domain;\n\n\nuse Illuminate\\Support\\Collection;\n\nclass BattleRounds extends Collection\n{\n\n}\n"
  },
  {
    "path": "app/Modules/Battle/Domain/BattleTurn.php",
    "content": "<?php\n\n\nnamespace App\\Modules\\Battle\\Domain;\n\nuse App\\Modules\\Character\\Domain\\Character;\nuse App\\Traits\\ThrowsDice;\n\n\nclass BattleTurn\n{\n    use ThrowsDice;\n\n    /**\n     * @var string\n     */\n    private $id;\n\n    /**\n     * @var Character\n     */\n    private $owner;\n\n    /**\n     * @var Character\n     */\n    private $target;\n\n    /**\n     * @var BattleTurnResult\n     */\n    private $result;\n\n    public function __construct(string $id, Character $owner, Character $target, BattleTurnResult $result)\n    {\n        $this->id = $id;\n        $this->owner = $owner;\n        $this->target = $target;\n        $this->result = $result;\n    }\n\n    public function execute()\n    {\n        if (!$this->isTargetHit()) {\n            $this->result = BattleTurnResult::miss();\n        }\n\n        $forceFactor = $this->owner->generateDamage();\n        $armorRating = $this->target->getArmorRating();\n\n        $isCriticalHit = $this->isCriticalHit();\n\n        $forceFactor = $isCriticalHit ? $forceFactor * 3 : $forceFactor;\n\n        $damage = max($forceFactor - $armorRating, 0);\n        $damageAbsorbed = $forceFactor - $damage;\n\n        $this->result = $isCriticalHit\n            ? BattleTurnResult::criticalHit($damage, $damageAbsorbed)\n            : BattleTurnResult::hit($damage, $damageAbsorbed);\n\n        $this->target->applyDamage($damage);\n    }\n\n    public function isOwnerAlive(): bool\n    {\n        return $this->owner->isAlive();\n    }\n\n    public function isTargetAlive(): bool\n    {\n        return $this->target->isAlive();\n    }\n\n    private function isTargetHit(): bool\n    {\n        $precision = $this->owner->generatePrecision();\n        $evasion = $this->target->generateEvasionFactor();\n\n        return $precision > $evasion;\n    }\n\n    private function isCriticalHit(): bool\n    {\n        $trickery = $this->owner->generateTrickery();\n        $awareness = $this->target->generateAwareness();\n\n        return $trickery > $awareness;\n    }\n\n    public function getId(): string\n    {\n        return $this->id;\n    }\n\n    public function getOwner(): Character\n    {\n        return $this->owner;\n    }\n\n    public function getTarget(): Character\n    {\n        return $this->target;\n    }\n\n    public function getDamageDone(): int\n    {\n        return $this->result->getDamageDone();\n    }\n\n    public function getDamageAbsorbed(): int\n    {\n        return $this->result->getDamageAbsorbed();\n    }\n\n    public function getResultType(): string\n    {\n        return $this->result->getType();\n    }\n}\n"
  },
  {
    "path": "app/Modules/Battle/Domain/BattleTurnResult.php",
    "content": "<?php\n\n\nnamespace App\\Modules\\Battle\\Domain;\n\n\nclass BattleTurnResult\n{\n    const NONE = 'none';\n    const MISS = 'miss';\n    const HIT = 'hit';\n    const CRITICAL_HIT = 'critical_hit';\n\n    const TYPES = [\n        self::NONE,\n        self::MISS,\n        self::HIT,\n        self::CRITICAL_HIT,\n    ];\n\n    /**\n     * @var string\n     */\n    private $type;\n\n    /**\n     * @var int\n     */\n    private $damageDone;\n\n    /**\n     * @var int\n     */\n    private $damageAbsorbed;\n\n    public function __construct(string $type, int $damageDone, int $damageAbsorbed)\n    {\n        $this->type = $type;\n        $this->damageDone = $damageDone;\n        $this->damageAbsorbed = $damageAbsorbed;\n    }\n\n    public static function none()\n    {\n        return new self(self::NONE, 0, 0);\n    }\n\n    public static function miss()\n    {\n        return new self(self::MISS, 0, 0);\n    }\n\n    public static function hit(int $damageDone, int $damageAbsorbed)\n    {\n        return new self(self::HIT, $damageDone, $damageAbsorbed);\n    }\n\n    public static function criticalHit(int $damageDone, int $damageAbsorbed)\n    {\n        return new self(self::CRITICAL_HIT, $damageDone, $damageAbsorbed);\n    }\n\n    public function getType(): string\n    {\n        return $this->type;\n    }\n\n    public function getDamageDone(): int\n    {\n        return $this->damageDone;\n    }\n\n    public function getDamageAbsorbed(): int\n    {\n        return $this->damageAbsorbed;\n    }\n}\n"
  },
  {
    "path": "app/Modules/Battle/Domain/BattleTurns.php",
    "content": "<?php\n\n\nnamespace App\\Modules\\Battle\\Domain;\n\n\nuse Illuminate\\Support\\Collection;\n\nclass BattleTurns extends Collection\n{\n\n}\n"
  },
  {
    "path": "app/Modules/Battle/Infrastructure/Repositories/BattleRepository.php",
    "content": "<?php\n\n\nnamespace App\\Modules\\Battle\\Infrastructure\\Repositories;\n\n\nuse App\\Modules\\Battle\\Application\\Contracts\\BattleRepositoryInterface;\nuse App\\Modules\\Battle\\Domain\\Battle;\nuse App\\Models\\Battle as BattleModel;\nuse App\\Models\\BattleRound as BattleRoundModel;\nuse App\\Modules\\Battle\\Domain\\BattleId;\nuse App\\Modules\\Battle\\Domain\\BattleRound;\nuse App\\Modules\\Battle\\Domain\\BattleTurn;\nuse App\\Traits\\GeneratesUuid;\nuse Exception;\n\nclass BattleRepository implements BattleRepositoryInterface\n{\n    use GeneratesUuid;\n\n    /**\n     * @return BattleId\n     *\n     * @throws Exception\n     */\n    public function nextIdentity(): BattleId\n    {\n        return BattleId::fromString($this->generateUuid());\n    }\n\n    public function add(Battle $battle): void\n    {\n        /** @var BattleModel $battleModel */\n        $battleModel = BattleModel::query()->create([\n            'id' => $battle->getId()->toString(),\n            'location_id' => $battle->getLocationId(),\n            'attacker_id' => $battle->getAttacker()->getId()->toString(),\n            'defender_id' => $battle->getDefender()->getId()->toString(),\n            'victor_id' => $battle->getVictor()->getId()->toString(),\n            'victor_xp_gained' => $battle->getVictorXpGained(),\n        ]);\n\n        /** @var BattleRound $round */\n        foreach ($battle->getRounds()->all() as $round) {\n\n            /** @var BattleRoundModel $roundModel */\n            $roundModel = $battleModel->rounds()->create([\n                'id' => $round->getId(),\n            ]);\n\n            /** @var BattleTurn $turn */\n            foreach ($round->getTurns()->all() as $turn) {\n                $roundModel->turns()->create([\n                    'id' => $turn->getId(),\n                    'damageDone' => $turn->getDamageDone(),\n                    'damageAbsorbed' => $turn->getDamageAbsorbed(),\n                    'result_type' => $turn->getResultType(),\n                    'executor_id' => $turn->getOwner()->getId()->toString(),\n                    'target_id' => $turn->getTarget()->getId()->toString(),\n                ]);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "app/Modules/Character/Application/Commands/AttackCharacterCommand.php",
    "content": "<?php\n\n\nnamespace App\\Modules\\Character\\Application\\Commands;\n\n\nuse App\\Modules\\Character\\Domain\\CharacterId;\n\nclass AttackCharacterCommand\n{\n    /**\n     * @var CharacterId\n     */\n    private $attackerId;\n    /**\n     * @var CharacterId\n     */\n    private $defenderId;\n\n    public function __construct(CharacterId $attackerId, CharacterId $defenderId)\n    {\n        $this->attackerId = $attackerId;\n        $this->defenderId = $defenderId;\n    }\n\n    public function getAttackerId(): CharacterId\n    {\n        return $this->attackerId;\n    }\n\n    public function getDefenderId(): CharacterId\n    {\n        return $this->defenderId;\n    }\n}\n"
  },
  {
    "path": "app/Modules/Character/Application/Commands/CreateCharacterCommand.php",
    "content": "<?php\n\n\nnamespace App\\Modules\\Character\\Application\\Commands;\n\n\nclass CreateCharacterCommand\n{\n\n    /**\n     * @var string\n     */\n    private $name;\n    /**\n     * @var string\n     */\n    private $gender;\n    /**\n     * @var string\n     */\n    private $type;\n\n    /**\n     * @var int\n     */\n    private $raceId;\n    /**\n     * @var string\n     */\n    private $userId;\n\n    public function __construct(string $name, string $gender, string $type, int $raceId, string $userId)\n    {\n        $this->name = $name;\n        $this->gender = $gender;\n        $this->type = $type;\n        $this->raceId = $raceId;\n        $this->userId = $userId;\n    }\n\n    public function getName(): string\n    {\n        return $this->name;\n    }\n\n    public function getGender(): string\n    {\n        return $this->gender;\n    }\n\n    public function getCharacterType(): string\n    {\n        return $this->type;\n    }\n\n    public function getRaceId(): int\n    {\n        return $this->raceId;\n    }\n\n    public function getUserId(): string\n    {\n        return $this->userId;\n    }\n}\n"
  },
  {
    "path": "app/Modules/Character/Application/Commands/IncreaseAttributeCommand.php",
    "content": "<?php\n\n\nnamespace App\\Modules\\Character\\Application\\Commands;\n\n\nuse App\\Modules\\Character\\Domain\\CharacterId;\n\nclass IncreaseAttributeCommand\n{\n    /**\n     * @var CharacterId\n     */\n    private $characterId;\n    /**\n     * @var string\n     */\n    private $attribute;\n\n    public function __construct(CharacterId $characterId, string $attribute)\n    {\n        $this->characterId = $characterId;\n        $this->attribute = $attribute;\n    }\n\n    public function getCharacterId(): CharacterId\n    {\n        return $this->characterId;\n    }\n\n    public function getAttribute(): string\n    {\n        return $this->attribute;\n    }\n}\n"
  },
  {
    "path": "app/Modules/Character/Application/Commands/MoveCharacterCommand.php",
    "content": "<?php\n\n\nnamespace App\\Modules\\Character\\Application\\Commands;\n\n\nuse App\\Modules\\Character\\Domain\\CharacterId;\n\nclass MoveCharacterCommand\n{\n    /**\n     * @var CharacterId\n     */\n    private $characterId;\n\n    /**\n     * @var string\n     */\n    private $locationId;\n\n    public function __construct(CharacterId $characterId, string $locationId)\n    {\n        $this->characterId = $characterId;\n        $this->locationId = $locationId;\n    }\n\n    public function getCharacterId(): CharacterId\n    {\n        return $this->characterId;\n    }\n\n    public function getLocationId(): string\n    {\n        return $this->locationId;\n    }\n}\n"
  },
  {
    "path": "app/Modules/Character/Application/Contracts/CharacterRepositoryInterface.php",
    "content": "<?php\n\nnamespace App\\Modules\\Character\\Application\\Contracts;\n\nuse App\\Modules\\Character\\Domain\\Character;\nuse App\\Modules\\Character\\Domain\\CharacterId;\n\ninterface CharacterRepositoryInterface\n{\n    public function nextIdentity(): CharacterId;\n\n    public function add(Character $character): void;\n\n    public function getOne(CharacterId $characterId): Character;\n\n    public function update(Character $character): void;\n}\n"
  },
  {
    "path": "app/Modules/Character/Application/Contracts/LocationRepositoryInterface.php",
    "content": "<?php\n\nnamespace App\\Modules\\Character\\Application\\Contracts;\n\nuse App\\Modules\\Character\\Domain\\LocationId;\n\ninterface LocationRepositoryInterface\n{\n    public function nextIdentity(): LocationId;\n}\n"
  },
  {
    "path": "app/Modules/Character/Application/Contracts/RaceRepositoryInterface.php",
    "content": "<?php\n\nnamespace App\\Modules\\Character\\Application\\Contracts;\n\nuse App\\Modules\\Character\\Domain\\Race;\n\ninterface RaceRepositoryInterface\n{\n    public function getOne(int $raceId): Race;\n}\n"
  },
  {
    "path": "app/Modules/Character/Application/Factories/CharacterFactory.php",
    "content": "<?php\n\n\nnamespace App\\Modules\\Character\\Application\\Factories;\n\nuse App\\Modules\\Character\\Application\\Commands\\CreateCharacterCommand;\nuse App\\Modules\\Character\\Domain\\CharacterId;\nuse App\\Modules\\Character\\Domain\\CharacterType;\nuse App\\Modules\\Character\\Domain\\Race;\nuse App\\Modules\\Equipment\\Domain\\Inventory;\nuse App\\Modules\\Character\\Domain\\Statistics;\nuse App\\Modules\\Character\\Domain\\Attributes;\nuse App\\Modules\\Character\\Domain\\Character;\nuse App\\Modules\\Character\\Domain\\Gender;\nuse App\\Modules\\Character\\Domain\\HitPoints;\nuse App\\Modules\\Character\\Domain\\Reputation;\n\n\nclass CharacterFactory\n{\n    public function create(CharacterId $characterId, CreateCharacterCommand $command, Race $race, Inventory $inventory): Character\n    {\n        return new Character(\n            $characterId,\n            $race->getId(),\n            1,\n            $race->getStartingLocationId(),\n            $command->getName(),\n            new Gender($command->getGender()),\n            new CharacterType($command->getCharacterType()),\n            0,\n            new Reputation(0),\n            new Attributes([\n                'strength' => $race->getStrength(),\n                'agility' => $race->getAgility(),\n                'constitution' => $race->getConstitution(),\n                'intelligence' => $race->getIntelligence(),\n                'charisma' => $race->getCharisma(),\n                'unassigned' => 0,\n            ]),\n            HitPoints::byRace($race),\n            new Statistics([\n                'battlesLost' => 0,\n                'battlesWon' => 0,\n            ]),\n            $inventory,\n            $command->getUserId()\n        );\n    }\n}\n"
  },
  {
    "path": "app/Modules/Character/Application/Services/CharacterService.php",
    "content": "<?php\n\n\nnamespace App\\Modules\\Character\\Application\\Services;\n\n\nuse App\\Modules\\Battle\\Application\\Contracts\\BattleRepositoryInterface;\nuse App\\Modules\\Battle\\Domain\\Battle;\nuse App\\Modules\\Battle\\Domain\\BattleId;\nuse App\\Modules\\Battle\\Domain\\BattleRounds;\nuse App\\Modules\\Character\\Application\\Contracts\\RaceRepositoryInterface;\nuse App\\Modules\\Character\\Domain\\CharacterId;\nuse App\\Modules\\Character\\Application\\Contracts\\CharacterRepositoryInterface;\nuse App\\Modules\\Character\\Domain\\Character;\nuse App\\Modules\\Character\\Application\\Commands\\AttackCharacterCommand;\nuse App\\Modules\\Character\\Application\\Commands\\CreateCharacterCommand;\nuse App\\Modules\\Character\\Application\\Commands\\IncreaseAttributeCommand;\nuse App\\Modules\\Character\\Application\\Commands\\MoveCharacterCommand;\nuse App\\Modules\\Character\\Application\\Factories\\CharacterFactory;\nuse App\\Modules\\Equipment\\Application\\Commands\\CreateInventoryCommand;\nuse App\\Modules\\Equipment\\Application\\Services\\InventoryService;\nuse App\\Modules\\Image\\Domain\\Image;\nuse App\\Modules\\Level\\Application\\Services\\LevelService;\nuse App\\Modules\\Trade\\Application\\Commands\\CreateStoreCommand;\nuse App\\Modules\\Trade\\Application\\Services\\CreateStoreService;\nuse Illuminate\\Support\\Facades\\DB;\n\nclass CharacterService\n{\n    /**\n     * @var CharacterFactory\n     */\n    private $characterFactory;\n    /**\n     * @var CharacterRepositoryInterface\n     */\n    private $characterRepository;\n    /**\n     * @var RaceRepositoryInterface\n     */\n    private $raceRepository;\n    /**\n     * @var BattleRepositoryInterface\n     */\n    private $battleRepository;\n    /**\n     * @var LevelService\n     */\n    private $levelService;\n    /**\n     * @var InventoryService\n     */\n    private $inventoryService;\n    /**\n     * @var CreateStoreService\n     */\n    private $storeService;\n\n    public function __construct(\n        CharacterFactory $characterFactory,\n        CharacterRepositoryInterface $characterRepository,\n        RaceRepositoryInterface $raceRepository,\n        BattleRepositoryInterface $battleRepository,\n        LevelService $levelService,\n        InventoryService $inventoryService,\n        CreateStoreService $storeService\n    )\n    {\n        $this->characterFactory = $characterFactory;\n        $this->characterRepository = $characterRepository;\n        $this->raceRepository = $raceRepository;\n        $this->battleRepository = $battleRepository;\n        $this->levelService = $levelService;\n        $this->inventoryService = $inventoryService;\n        $this->storeService = $storeService;\n    }\n\n    public function create(CreateCharacterCommand $command): Character\n    {\n        $characterId = $this->characterRepository->nextIdentity();\n\n        $character = $this->characterFactory->create(\n            $characterId,\n            $command,\n            $this->raceRepository->getOne($command->getRaceId()),\n            $this->inventoryService->create(new CreateInventoryCommand($characterId))\n        );\n\n        $this->characterRepository->add($character);\n\n        $this->storeService->create(new CreateStoreCommand($characterId));\n\n        return $character;\n    }\n\n    public function increaseAttribute(IncreaseAttributeCommand $command): void\n    {\n        $character = $this->characterRepository->getOne($command->getCharacterId());\n\n        $character->applyAttributeIncrease($command->getAttribute());\n\n        $this->characterRepository->update($character);\n    }\n\n    public function move(MoveCharacterCommand $command): void\n    {\n        $character = $this->characterRepository->getOne($command->getCharacterId());\n\n        $character->setLocationId($command->getLocationId());\n\n        $this->characterRepository->update($character);\n    }\n\n    public function attack(AttackCharacterCommand $command): BattleId\n    {\n        return DB::transaction(function () use ($command) {\n\n            $attacker = $this->characterRepository->getOne($command->getAttackerId());\n            $defender = $this->characterRepository->getOne($command->getDefenderId());\n\n            $battleId = $this->battleRepository->nextIdentity();\n\n            $battle = new Battle(\n                $battleId,\n                $defender->getLocationId(),\n                $attacker,\n                $defender,\n                new BattleRounds(),\n                0\n            );\n\n            $battle->execute();\n\n            $victor = $battle->getVictor();\n            $loser = $battle->getLoser();\n\n            $victor->incrementWonBattles();\n            $loser->incrementLostBattles();\n\n            $victor->addXp($battle->getVictorXpGained());\n\n            $newLevel = $this->levelService->getLevelByXp($victor->getXp());\n\n            $victor->updateLevel($newLevel->getId());\n\n            $this->characterRepository->update($victor);\n            $this->characterRepository->update($loser);\n            $this->battleRepository->add($battle);\n\n            return $battleId;\n        });\n    }\n\n    public function updateProfilePicture(Image $picture): void\n    {\n        $character = $this->characterRepository->getOne($picture->getCharacterId());\n\n        $character->setProfilePictureId($picture->getId());\n\n        $this->characterRepository->update($character);\n    }\n\n    public function removeProfilePicture(CharacterId $characterId): void\n    {\n        $character = $this->characterRepository->getOne($characterId);\n\n        $character->removeProfilePicture();\n\n        $this->characterRepository->update($character);\n    }\n}\n"
  },
  {
    "path": "app/Modules/Character/Domain/Attributes.php",
    "content": "<?php\n\n\nnamespace App\\Modules\\Character\\Domain;\n\n\nuse Illuminate\\Support\\Collection;\n\nclass Attributes\n{\n    /**\n     * @var Collection\n     */\n    private $collection;\n\n    public function __construct($items = [])\n    {\n        $this->collection = new Collection($items);\n    }\n\n    public function addAvailablePoints(int $points): Attributes\n    {\n        $rawData = $this->collection->all();\n\n        $rawData['unassigned'] += $points;\n\n        return new static($rawData);\n    }\n\n    public function assignAvailablePoint(string $attribute): Attributes\n    {\n        $rawData = $this->collection->all();\n\n        $rawData['unassigned']--;\n        $rawData[$attribute]++;\n\n        return new static($rawData);\n    }\n\n    public function hasAvailablePoints(): bool\n    {\n        return (bool)$this->collection->get('unassigned');\n    }\n\n    public function getStrength(): int\n    {\n        return $this->collection->get('strength');\n    }\n\n    public function getAgility(): int\n    {\n        return $this->collection->get('agility');\n    }\n\n    public function getConstitution(): int\n    {\n        return $this->collection->get('constitution');\n    }\n\n    public function getIntelligence(): int\n    {\n        return $this->collection->get('intelligence');\n    }\n\n    public function getCharisma(): int\n    {\n        return $this->collection->get('charisma');\n    }\n\n    public function getUnassignedAttributePoints(): int\n    {\n        return $this->collection->get('unassigned');\n    }\n}\n"
  },
  {
    "path": "app/Modules/Character/Domain/Character.php",
    "content": "<?php\n\n\nnamespace App\\Modules\\Character\\Domain;\n\nuse App\\Modules\\Equipment\\Domain\\Inventory;\nuse App\\Modules\\Equipment\\Domain\\Item;\nuse App\\Modules\\Equipment\\Domain\\ItemEffect;\nuse App\\Modules\\Equipment\\Domain\\Money;\nuse App\\Modules\\Image\\Domain\\ImageId;\nuse App\\Traits\\ThrowsDice;\n\nclass Character\n{\n    use ThrowsDice;\n\n    /**\n     * @var string\n     */\n    private $name;\n    /**\n     * @var Gender\n     */\n    private $gender;\n    /**\n     * @var CharacterType\n     */\n    private $type;\n    /**\n     * @var int\n     */\n    private $levelId;\n    /**\n     * @var int\n     */\n    private $raceId;\n    /**\n     * @var string\n     */\n    private $locationId;\n    /**\n     * @var int\n     */\n    private $xp;\n    /**\n     * @var Reputation\n     */\n    private $reputation;\n    /**\n     * @var Attributes\n     */\n    private $attributes;\n    /**\n     * @var HitPoints\n     */\n    private $hitPoints;\n    /**\n     * @var CharacterId\n     */\n    private $id;\n    /**\n     * @var Statistics\n     */\n    private $statistics;\n    /**\n     * @var Inventory\n     */\n    private $inventory;\n    /**\n     * @var int|null\n     */\n    private $userId;\n    /**\n     * @var ImageId\n     */\n    private $profilePictureId;\n\n    public function __construct(\n        CharacterId $id,\n        int $raceId,\n        int $levelId,\n        string $locationId,\n        string $name,\n        Gender $gender,\n        CharacterType $type,\n        int $xp,\n        Reputation $reputation,\n        Attributes $attributes,\n        HitPoints $hitPoints,\n        Statistics $statistics,\n        Inventory $inventory,\n        int $userId = null,\n        ImageId $profilePictureId = null\n    ) {\n        $this->id = $id;\n        $this->name = $name;\n        $this->gender = $gender;\n        $this->type = $type;\n        $this->levelId = $levelId;\n        $this->raceId = $raceId;\n        $this->locationId = $locationId;\n        $this->xp = $xp;\n        $this->reputation = $reputation;\n        $this->attributes = $attributes;\n        $this->hitPoints = $hitPoints;\n        $this->statistics = $statistics;\n        $this->inventory = $inventory;\n        $this->userId = $userId;\n        $this->profilePictureId = $profilePictureId;\n    }\n\n    public function getLevelNumber(): int\n    {\n        return $this->levelId;\n    }\n\n    public function getId(): CharacterId\n    {\n        return $this->id;\n    }\n\n    public function generateDamage(): int\n    {\n        return self::throwOneDice() + $this->getBaseDamage();\n    }\n\n    public function getBaseDamage(): int\n    {\n        return $this->getStrength()\n            + $this->inventory->getEquippedItemsEffect(ItemEffect::DAMAGE);\n    }\n\n    public function generatePrecision(): int\n    {\n        return self::throwTwoDices() + $this->getBasePrecision();\n    }\n\n    public function getBasePrecision(): int\n    {\n        return $this->getAgility()\n            + $this->inventory->getEquippedItemsEffect(ItemEffect::PRECISION);\n    }\n\n    public function generateEvasionFactor(): int\n    {\n        return self::throwTwoDices() + $this->getBaseEvasion();\n    }\n\n    public function getBaseEvasion(): int\n    {\n        return $this->getAgility()\n            + $this->inventory->getEquippedItemsEffect(ItemEffect::EVASION);\n    }\n\n    public function generateTrickery(): int\n    {\n        return self::throwOneDice() + $this->getBaseTrickery();\n    }\n\n    public function getBaseTrickery(): int\n    {\n        return $this->getIntelligence()\n            + $this->inventory->getEquippedItemsEffect(ItemEffect::TRICKERY);\n    }\n\n    public function generateAwareness(): int\n    {\n        return self::throwTreeDices() + $this->getBaseAwareness();\n    }\n\n    public function getBaseAwareness(): int\n    {\n        return $this->getIntelligence() * 2\n            + $this->inventory->getEquippedItemsEffect(ItemEffect::AWARENESS);\n    }\n\n    public function getArmorRating(): int\n    {\n        return $this->inventory->getEquippedItemsEffect(ItemEffect::ARMOR);\n    }\n\n    public function getStrength(): int\n    {\n        return $this->attributes->getStrength();\n    }\n\n    public function getAgility(): int\n    {\n        return $this->attributes->getAgility();\n    }\n\n    public function getConstitution(): int\n    {\n        return $this->attributes->getConstitution();\n    }\n\n    public function getIntelligence(): int\n    {\n        return $this->attributes->getIntelligence();\n    }\n\n    public function getCharisma(): int\n    {\n        return $this->attributes->getCharisma();\n    }\n\n    public function getUnassignedAttributePoints(): int\n    {\n        return $this->attributes->getUnassignedAttributePoints();\n    }\n\n    public function getLocationId(): string\n    {\n        return $this->locationId;\n    }\n\n    public function getHitPoints(): int\n    {\n        return $this->hitPoints->getCurrentHitPoints();\n    }\n\n    public function getTotalHitPoints(): int\n    {\n        return $this->hitPoints->getMaximumHitPoints();\n    }\n\n    public function equals(Character $other): bool\n    {\n        return $this->getId()->equals($other->getId());\n    }\n\n    public function getName(): string\n    {\n        return $this->name;\n    }\n\n    public function getUserId(): ?int\n    {\n        return $this->userId;\n    }\n\n    public function getGender(): Gender\n    {\n        return $this->gender;\n    }\n\n    public function getType(): CharacterType\n    {\n        return $this->type;\n    }\n\n    public function getXp(): int\n    {\n        return $this->xp;\n    }\n\n    public function getRaceId(): int\n    {\n        return $this->raceId;\n    }\n\n    public function getMoney(): Money\n    {\n        return $this->inventory->getMoney();\n    }\n\n    public function getReputation(): Reputation\n    {\n        return $this->reputation;\n    }\n\n    public function applyAttributeIncrease(string $attribute): void\n    {\n        if ($this->attributes->hasAvailablePoints()) {\n\n            $this->attributes = $this->attributes->assignAvailablePoint($attribute);\n\n            if ($attribute === 'constitution') {\n                $this->hitPoints = $this->hitPoints->withIncrementedConstitution();\n            }\n        }\n    }\n\n    public function addItemToInventory(Item $item): void\n    {\n        $this->inventory->add($item);\n    }\n\n    public function setLocationId(string $locationId): void\n    {\n        $this->locationId = $locationId;\n    }\n\n    public function isAlive(): bool\n    {\n        return $this->hitPoints->getCurrentHitPoints() > 0;\n    }\n\n    public function incrementWonBattles(): void\n    {\n        $this->statistics = $this->statistics->withIncreaseWonBattles();\n    }\n\n    public function incrementLostBattles(): void\n    {\n        $this->statistics = $this->statistics->withIncreaseLostBattles();\n    }\n\n    public function addXp(int $xp): void\n    {\n        $this->xp += $xp;\n    }\n\n    public function getBattlesWon(): int\n    {\n        return $this->statistics->getBattlesWon();\n    }\n\n    public function getBattlesLost(): int\n    {\n        return $this->statistics->getBattlesLost();\n    }\n\n    public function applyDamage($damageDone): void\n    {\n        $this->hitPoints = $this->hitPoints->withUpdatedCurrentValue(-$damageDone);\n    }\n\n    public function updateLevel(int $levelId): void\n    {\n        $points = $levelId - $this->levelId;\n\n        $this->levelId = $levelId;\n\n        $this->attributes = $this->attributes->addAvailablePoints($points);\n    }\n\n    public function setProfilePictureId(ImageId $profilePictureId): void\n    {\n        $this->profilePictureId = $profilePictureId;\n    }\n\n    /**\n     * @return ImageId|null\n     */\n    public function getProfilePictureId(): ?ImageId\n    {\n        return $this->profilePictureId;\n    }\n\n    public function removeProfilePicture(): void\n    {\n        $this->profilePictureId = null;\n    }\n\n    public function getInventory(): Inventory\n    {\n        return $this->inventory;\n    }\n\n    public function isMerchant(): bool\n    {\n        return $this->type->isMerchant();\n    }\n}\n"
  },
  {
    "path": "app/Modules/Character/Domain/CharacterId.php",
    "content": "<?php declare(strict_types=1);\n\n\nnamespace App\\Modules\\Character\\Domain;\n\n\nuse App\\Modules\\Generic\\Domain\\BaseId;\n\nclass CharacterId extends BaseId\n{\n}\n"
  },
  {
    "path": "app/Modules/Character/Domain/CharacterType.php",
    "content": "<?php\n\n\nnamespace App\\Modules\\Character\\Domain;\n\nuse InvalidArgumentException;\n\nclass CharacterType\n{\n    public const PLAYER = 'player';\n    public const MERCHANT = 'merchant';\n    public const CIVILIAN = 'civilian';\n    public const MONSTER = 'monster';\n\n    public const TYPES = [\n        self::PLAYER,\n        self::MERCHANT,\n        self::CIVILIAN,\n        self::MONSTER,\n    ];\n\n    private $value;\n\n    public function __construct(string $value)\n    {\n        if (!in_array($value, self::TYPES, true)) {\n            throw new InvalidArgumentException(\"$value is not a valid Character Type\");\n        }\n\n        $this->value = $value;\n    }\n\n    public function getValue(): string\n    {\n        return $this->value;\n    }\n\n    public function isMerchant(): bool\n    {\n        return $this->value === self::MERCHANT;\n    }\n}\n"
  },
  {
    "path": "app/Modules/Character/Domain/Gender.php",
    "content": "<?php\n\n\nnamespace App\\Modules\\Character\\Domain;\n\n\nclass Gender\n{\n    /**\n     * @var string\n     */\n    private $value;\n\n    public function __construct(string $value)\n    {\n        $this->value = $value;\n    }\n\n    public function getValue(): string\n    {\n        return $this->value;\n    }\n}\n"
  },
  {
    "path": "app/Modules/Character/Domain/HitPoints.php",
    "content": "<?php\n\n\nnamespace App\\Modules\\Character\\Domain;\n\n\nuse App\\Traits\\ThrowsDice;\n\nclass HitPoints\n{\n    use ThrowsDice;\n\n    /**\n     * @var int\n     */\n    private $currentHitPoints;\n\n    /**\n     * @var int\n     */\n    private $maximumHitPoints;\n\n    public static function byRace(Race $race): HitPoints\n    {\n        $maximumHitPoints = self::constitutionToHitPoints($race->getConstitution());\n\n        return new HitPoints($maximumHitPoints, $maximumHitPoints);\n    }\n\n    public function withIncrementedConstitution(): HitPoints\n    {\n        return new HitPoints(\n            $this->currentHitPoints,\n            $this->maximumHitPoints + self::constitutionToHitPoints(1)\n        );\n    }\n\n    public function withUpdatedCurrentValue(int $points): HitPoints\n    {\n        return new HitPoints(\n            $this->currentHitPoints + $points,\n            $this->maximumHitPoints\n        );\n    }\n\n    protected static function constitutionToHitPoints(int $constitutionPoints): int\n    {\n        return $constitutionPoints * 10 + self::throwTwoDices();\n    }\n\n    public function __construct(int $currentHitPoints, int $maximumHitPoints)\n    {\n        $this->currentHitPoints = $currentHitPoints;\n        $this->maximumHitPoints = $maximumHitPoints;\n    }\n\n    public function getCurrentHitPoints(): int\n    {\n        return $this->currentHitPoints;\n    }\n\n    public function getMaximumHitPoints(): int\n    {\n        return $this->maximumHitPoints;\n    }\n}\n"
  },
  {
    "path": "app/Modules/Character/Domain/LocationId.php",
    "content": "<?php declare(strict_types=1);\n\n\nnamespace App\\Modules\\Character\\Domain;\n\n\nuse App\\Modules\\Generic\\Domain\\BaseId;\n\nclass LocationId extends BaseId\n{\n}\n"
  },
  {
    "path": "app/Modules/Character/Domain/Name.php",
    "content": "<?php\n\n\nnamespace App\\Modules\\Character\\Domain;\n\n\nclass Name\n{\n    /**\n     * @var string\n     */\n    private $value;\n\n    public function __construct(string $value)\n    {\n        $this->value = $value;\n    }\n\n    public function getValue(): string\n    {\n        return $this->value;\n    }\n\n    public function equals(Name $otherName): bool\n    {\n        return $this->value === $otherName->value;\n    }\n}\n"
  },
  {
    "path": "app/Modules/Character/Domain/Race.php",
    "content": "<?php\n\n\nnamespace App\\Modules\\Character\\Domain;\n\nclass Race\n{\n    /**\n     * @var int\n     */\n    private $id;\n    /**\n     * @var string\n     */\n    private $startingLocationId;\n    /**\n     * @var string\n     */\n    private $name;\n    /**\n     * @var string\n     */\n    private $description;\n    /**\n     * @var string\n     */\n    private $maleImage;\n    /**\n     * @var string\n     */\n    private $femaleImage;\n    /**\n     * @var Attributes\n     */\n    private $attributes;\n\n    public function __construct(\n        int $id,\n        string $startingLocationId,\n        string $name,\n        string $description,\n        string $maleImage,\n        string $femaleImage,\n        Attributes $attributes\n    ) {\n        $this->id = $id;\n        $this->startingLocationId = $startingLocationId;\n        $this->name = $name;\n        $this->description = $description;\n        $this->maleImage = $maleImage;\n        $this->femaleImage = $femaleImage;\n        $this->attributes = $attributes;\n    }\n\n    public function getId(): int\n    {\n        return $this->id;\n    }\n\n    public function getName(): string\n    {\n        return $this->name;\n    }\n\n    public function getImageByGender(string $gender):string\n    {\n        return $this->{\"{$gender}_image\"};\n    }\n\n    public function getStartingLocationId(): string\n    {\n        return $this->startingLocationId;\n    }\n\n    public function getStrength(): int\n    {\n        return $this->attributes->getStrength();\n    }\n\n    public function getAgility(): int\n    {\n        return $this->attributes->getAgility();\n    }\n\n    public function getConstitution(): int\n    {\n        return $this->attributes->getConstitution();\n    }\n\n    public function getIntelligence(): int\n    {\n        return $this->attributes->getIntelligence();\n    }\n\n    public function getCharisma(): int\n    {\n        return $this->attributes->getCharisma();\n    }\n\n    /**\n     * @return string\n     */\n    public function getDescription(): string\n    {\n        return $this->description;\n    }\n\n    /**\n     * @return string\n     */\n    public function getMaleImage(): string\n    {\n        return $this->maleImage;\n    }\n\n    /**\n     * @return string\n     */\n    public function getFemaleImage(): string\n    {\n        return $this->femaleImage;\n    }\n}\n"
  },
  {
    "path": "app/Modules/Character/Domain/Reputation.php",
    "content": "<?php\n\n\nnamespace App\\Modules\\Character\\Domain;\n\n\nclass Reputation\n{\n    /**\n     * @var int\n     */\n    private $value;\n\n    public function __construct(int $value)\n    {\n        $this->value = $value;\n    }\n\n    public function getValue(): int\n    {\n        return $this->value;\n    }\n}\n"
  },
  {
    "path": "app/Modules/Character/Domain/Statistics.php",
    "content": "<?php\n\n\nnamespace App\\Modules\\Character\\Domain;\n\n\nuse Illuminate\\Support\\Collection;\n\nclass Statistics\n{\n    private $statistics;\n\n    public function __construct($statistics = [])\n    {\n        $this->statistics = new Collection($statistics);\n    }\n\n    public function withIncreaseWonBattles(): Statistics\n    {\n        $data = $this->statistics->all();\n\n        $data['battlesWon']++;\n\n        return new self($data);\n    }\n\n    public function withIncreaseLostBattles(): Statistics\n    {\n        $data = $this->statistics->all();\n\n        $data['battlesLost']++;\n\n        return new self($data);\n    }\n\n    public function getBattlesWon(): int\n    {\n        return (int)$this->statistics->get('battlesWon');\n    }\n\n    public function getBattlesLost(): int\n    {\n        return (int)$this->statistics->get('battlesLost');\n    }\n}\n"
  },
  {
    "path": "app/Modules/Character/Infrastructure/ReconstitutionFactories/CharacterReconstitutionFactory.php",
    "content": "<?php\n\n\nnamespace App\\Modules\\Character\\Infrastructure\\ReconstitutionFactories;\n\nuse App\\Modules\\Character\\Domain\\CharacterId;\nuse App\\Modules\\Character\\Domain\\CharacterType;\nuse App\\Modules\\Equipment\\Infrastructure\\ReconstitutionFactories\\InventoryReconstitutionFactory;\nuse App\\Modules\\Character\\Domain\\Attributes;\nuse App\\Modules\\Character\\Domain\\Character;\nuse App\\Modules\\Character\\Domain\\Gender;\nuse App\\Modules\\Character\\Domain\\Statistics;\nuse App\\Modules\\Character\\Domain\\HitPoints;\nuse App\\Modules\\Character\\Domain\\Reputation;\nuse App\\Models\\Character as CharacterModel;\nuse App\\Modules\\Image\\Domain\\ImageId;\n\n\nclass CharacterReconstitutionFactory\n{\n    /**\n     * @var InventoryReconstitutionFactory\n     */\n    private $inventoryReconstitutionFactory;\n\n    public function __construct(InventoryReconstitutionFactory $inventoryReconstitutionFactory)\n    {\n        $this->inventoryReconstitutionFactory = $inventoryReconstitutionFactory;\n    }\n\n    public function reconstitute(CharacterModel $characterModel): Character\n    {\n        $inventory = $this->inventoryReconstitutionFactory->reconstitute($characterModel->inventory);\n\n        $profilePictureId = $characterModel->getProfilePictureId();\n\n        $character = new Character(\n            CharacterId::fromString($characterModel->getId()),\n            $characterModel->getRaceId(),\n            $characterModel->getLevelNumber(),\n            $characterModel->getLocationId(),\n            $characterModel->getName(),\n            new Gender($characterModel->getGender()),\n            new CharacterType($characterModel->getType()),\n            $characterModel->getXp(),\n            new Reputation(0),\n            new Attributes([\n                'strength' => $characterModel->getStrength(),\n                'agility' => $characterModel->getAgility(),\n                'constitution' => $characterModel->getConstitution(),\n                'intelligence' => $characterModel->getIntelligence(),\n                'charisma' => $characterModel->getCharisma(),\n                'unassigned' => $characterModel->getAvailableAttributePoints(),\n            ]),\n            new HitPoints(\n                $characterModel->getHitPoints(),\n                $characterModel->getTotalHitPoints()\n            ),\n            new Statistics([\n                'battlesLost' => $characterModel->getBattlesLost(),\n                'battlesWon' => $characterModel->getBattlesWon(),\n            ]),\n            $inventory,\n            $characterModel->getUserId(),\n            $profilePictureId ? ImageId::fromString($profilePictureId) : null\n        );\n\n        return $character;\n    }\n}\n"
  },
  {
    "path": "app/Modules/Character/Infrastructure/Repositories/CharacterRepository.php",
    "content": "<?php\n\nnamespace App\\Modules\\Character\\Infrastructure\\Repositories;\n\nuse App\\Modules\\Character\\Application\\Contracts\\CharacterRepositoryInterface;\nuse App\\Modules\\Character\\Domain\\Character;\nuse App\\Models\\Character as CharacterModel;\nuse App\\Modules\\Character\\Domain\\CharacterId;\nuse App\\Modules\\Character\\Infrastructure\\ReconstitutionFactories\\CharacterReconstitutionFactory;\nuse App\\Traits\\GeneratesUuid;\nuse Exception;\n\nclass CharacterRepository implements CharacterRepositoryInterface\n{\n    use GeneratesUuid;\n\n    /**\n     * @var CharacterReconstitutionFactory\n     */\n    private $characterReconstitutionFactory;\n\n    public function __construct(CharacterReconstitutionFactory $characterReconstitutionFactory)\n    {\n        $this->characterReconstitutionFactory = $characterReconstitutionFactory;\n    }\n\n    /**\n     * @return CharacterId\n     *\n     * @throws Exception\n     */\n    public function nextIdentity(): CharacterId\n    {\n        return CharacterId::fromString($this->generateUuid());\n    }\n\n    public function add(Character $character): void\n    {\n        $profilePictureId = $character->getProfilePictureId();\n\n        /** @var CharacterModel $characterModel */\n        CharacterModel::query()->create([\n            'id' => $character->getId()->toString(),\n            'user_id' => $character->getUserId(),\n\n            'name' => $character->getName(),\n            'gender' => $character->getGender()->getValue(),\n            'type' => $character->getType()->getValue(),\n\n            'xp' => $character->getXp(),\n            'level_id' => $character->getLevelNumber(),\n            'reputation' => $character->getReputation()->getValue(),\n\n            'strength' => $character->getStrength(),\n            'agility' => $character->getAgility(),\n            'constitution' => $character->getConstitution(),\n            'intelligence' => $character->getIntelligence(),\n            'charisma' => $character->getCharisma(),\n\n            'hit_points' => $character->getHitPoints(),\n            'total_hit_points' => $character->getTotalHitPoints(),\n\n            'race_id' => $character->getRaceId(),\n            'location_id' => $character->getLocationId(),\n\n            'battles_won' => $character->getBattlesWon(),\n            'battles_lost' => $character->getBattlesLost(),\n\n            'profile_picture_id' => $profilePictureId ? $profilePictureId->toString() : null,\n        ]);\n    }\n\n    public function getOne(CharacterId $characterId): Character\n    {\n        /** @var CharacterModel $characterModel */\n        $characterModel = CharacterModel::query()->with('inventory')->findOrFail($characterId->toString());\n\n        return $this->characterReconstitutionFactory->reconstitute($characterModel);\n    }\n\n    public function update(Character $character): void\n    {\n        /** @var CharacterModel $characterModel */\n        $characterModel = CharacterModel::query()->findOrFail($character->getId()->toString());\n\n        $profilePictureId = $character->getProfilePictureId();\n\n        $characterModel->update([\n            'name' => $character->getName(),\n            'gender' => $character->getGender()->getValue(),\n\n            'xp' => $character->getXp(),\n            'level_id' => $character->getLevelNumber(),\n            'reputation' => $character->getReputation()->getValue(),\n\n            'strength' => $character->getStrength(),\n            'agility' => $character->getAgility(),\n            'constitution' => $character->getConstitution(),\n            'intelligence' => $character->getIntelligence(),\n            'charisma' => $character->getCharisma(),\n            'available_attribute_points' => $character->getUnassignedAttributePoints(),\n\n            'hit_points' => $character->getHitPoints(),\n            'total_hit_points' => $character->getTotalHitPoints(),\n\n            'battles_won' => $character->getBattlesWon(),\n            'battles_lost' => $character->getBattlesLost(),\n\n            'location_id' => $character->getLocationId(),\n\n            'profile_picture_id' => $profilePictureId ? $profilePictureId->toString() : null,\n        ]);\n    }\n}\n"
  },
  {
    "path": "app/Modules/Character/Infrastructure/Repositories/LocationRepository.php",
    "content": "<?php\n\nnamespace App\\Modules\\Character\\Infrastructure\\Repositories;\n\nuse App\\Modules\\Character\\Application\\Contracts\\LocationRepositoryInterface;\nuse App\\Modules\\Character\\Domain\\LocationId;\nuse App\\Traits\\GeneratesUuid;\nuse Exception;\n\nclass LocationRepository implements LocationRepositoryInterface\n{\n    use GeneratesUuid;\n\n    /**\n     * @return LocationId\n     *\n     * @throws Exception\n     */\n    public function nextIdentity(): LocationId\n    {\n        return LocationId::fromString($this->generateUuid());\n    }\n}\n"
  },
  {
    "path": "app/Modules/Character/Infrastructure/Repositories/RaceRepository.php",
    "content": "<?php\n\nnamespace App\\Modules\\Character\\Infrastructure\\Repositories;\n\nuse App\\Modules\\Character\\Application\\Contracts\\RaceRepositoryInterface;\nuse App\\Modules\\Character\\Domain\\Attributes;\nuse App\\Modules\\Character\\Domain\\Race;\nuse App\\Models\\Race as RaceModel;\n\nclass RaceRepository implements RaceRepositoryInterface\n{\n    public function getOne(int $raceId): Race\n    {\n        /** @var RaceModel $race */\n        $race = RaceModel::query()->findOrFail($raceId);\n\n        return new Race(\n            $race->getId(),\n            $race->getStartingLocationId(),\n            $race->getName(),\n            $race->getDescription(),\n            $race->getMaleImage(),\n            $race->getFemaleImage(),\n            new Attributes([\n                'strength' => $race->getStrength(),\n                'agility' => $race->getAgility(),\n                'constitution' => $race->getConstitution(),\n                'intelligence' => $race->getIntelligence(),\n                'charisma' => $race->getCharisma(),\n            ])\n        );\n    }\n}\n"
  },
  {
    "path": "app/Modules/Character/UI/Http/CommandMappers/AttackCharacterCommandMapper.php",
    "content": "<?php\n\n\nnamespace App\\Modules\\Character\\UI\\Http\\CommandMappers;\n\nuse App\\Modules\\Character\\Application\\Commands\\AttackCharacterCommand;\nuse App\\Modules\\Character\\Domain\\CharacterId;\nuse App\\Models\\User as UserModel;\nuse Illuminate\\Http\\Request;\n\nclass AttackCharacterCommandMapper\n{\n    public function map(Request $request, string $defenderId): AttackCharacterCommand\n    {\n        /** @var UserModel $authenticatedUser */\n        $userModel = $request->user();\n\n        return new AttackCharacterCommand(\n            CharacterId::fromString($userModel->character->getId()),\n            CharacterId::fromString($defenderId)\n        );\n    }\n}\n"
  },
  {
    "path": "app/Modules/Character/UI/Http/CommandMappers/CreateCharacterCommandMapper.php",
    "content": "<?php\n\n\nnamespace App\\Modules\\Character\\UI\\Http\\CommandMappers;\n\nuse App\\Modules\\Character\\Application\\Commands\\CreateCharacterCommand;\nuse App\\Modules\\Character\\Domain\\CharacterType;\nuse Illuminate\\Http\\Request;\nuse App\\Models\\User as UserModel;\n\nclass CreateCharacterCommandMapper\n{\n    public function map(Request $request): CreateCharacterCommand\n    {\n        /** @var UserModel $userModel */\n        $userModel = $request->user();\n\n        return new CreateCharacterCommand(\n            $request->input('name'),\n            $request->input('gender'),\n            CharacterType::PLAYER,\n            $request->input('race_id'),\n            $userModel->getId()\n        );\n    }\n}\n"
  },
  {
    "path": "app/Modules/Character/UI/Http/CommandMappers/IncreaseAttributeCommandMapper.php",
    "content": "<?php\n\n\nnamespace App\\Modules\\Character\\UI\\Http\\CommandMappers;\n\nuse App\\Modules\\Character\\Application\\Commands\\IncreaseAttributeCommand;\nuse App\\Modules\\Character\\Domain\\CharacterId;\nuse Illuminate\\Http\\Request;\n\nclass IncreaseAttributeCommandMapper\n{\n    public function map(string $characterId, Request $request): IncreaseAttributeCommand\n    {\n        return new IncreaseAttributeCommand(\n            CharacterId::fromString($characterId),\n            $request->input('attribute')\n        );\n    }\n}\n"
  },
  {
    "path": "app/Modules/Character/UI/Http/CommandMappers/MoveCharacterCommandMapper.php",
    "content": "<?php\n\n\nnamespace App\\Modules\\Character\\UI\\Http\\CommandMappers;\n\nuse App\\Modules\\Character\\Application\\Commands\\MoveCharacterCommand;\nuse App\\Modules\\Character\\Domain\\CharacterId;\n\nclass MoveCharacterCommandMapper\n{\n    public function map(string $characterId, string $locationId): MoveCharacterCommand\n    {\n        return new MoveCharacterCommand(\n            CharacterId::fromString($characterId),\n            $locationId\n        );\n    }\n}\n"
  },
  {
    "path": "app/Modules/Equipment/Application/Commands/AddItemToInventoryCommand.php",
    "content": "<?php\n\nnamespace App\\Modules\\Equipment\\Application\\Commands;\n\nuse App\\Modules\\Character\\Domain\\CharacterId;\nuse App\\Modules\\Equipment\\Domain\\ItemId;\n\nclass AddItemToInventoryCommand\n{\n    /**\n     * @var CharacterId\n     */\n    private $characterId;\n    /**\n     * @var int\n     */\n    private $slot;\n    /**\n     * @var ItemId\n     */\n    private $itemId;\n\n    public function __construct(CharacterId $characterId, int $slot, ItemId $itemId)\n    {\n        $this->characterId = $characterId;\n        $this->slot = $slot;\n        $this->itemId = $itemId;\n    }\n\n    public function getCharacterId(): CharacterId\n    {\n        return $this->characterId;\n    }\n\n    public function getSlot(): int\n    {\n        return $this->slot;\n    }\n\n    public function getItemId(): ItemId\n    {\n        return $this->itemId;\n    }\n}\n"
  },
  {
    "path": "app/Modules/Equipment/Application/Commands/CreateInventoryCommand.php",
    "content": "<?php declare(strict_types=1);\n\n\nnamespace App\\Modules\\Equipment\\Application\\Commands;\n\n\nuse App\\Modules\\Character\\Domain\\CharacterId;\n\nclass CreateInventoryCommand\n{\n    /**\n     * @var CharacterId\n     */\n    private $characterId;\n\n    public function __construct(CharacterId $characterId)\n    {\n        $this->characterId = $characterId;\n    }\n\n    public function getCharacterId(): CharacterId\n    {\n        return $this->characterId;\n    }\n}\n"
  },
  {
    "path": "app/Modules/Equipment/Application/Commands/CreateItemCommand.php",
    "content": "<?php\n\nnamespace App\\Modules\\Equipment\\Application\\Commands;\n\nuse App\\Modules\\Character\\Domain\\CharacterId;\nuse App\\Modules\\Equipment\\Domain\\ItemPrototypeId;\n\nclass CreateItemCommand\n{\n    /**\n     * @var ItemPrototypeId\n     */\n    private $prototypeId;\n    /**\n     * @var CharacterId\n     */\n    private $creatorCharacterId;\n\n    public function __construct(ItemPrototypeId $prototypeId, CharacterId $creatorCharacterId)\n    {\n        $this->prototypeId = $prototypeId;\n        $this->creatorCharacterId = $creatorCharacterId;\n    }\n\n    public function getPrototypeId(): ItemPrototypeId\n    {\n        return $this->prototypeId;\n    }\n\n    public function getCreatorCharacterId(): CharacterId\n    {\n        return $this->creatorCharacterId;\n    }\n}\n"
  },
  {
    "path": "app/Modules/Equipment/Application/Commands/EquipItemCommand.php",
    "content": "<?php\n\nnamespace App\\Modules\\Equipment\\Application\\Commands;\n\nuse App\\Modules\\Character\\Domain\\CharacterId;\nuse App\\Modules\\Equipment\\Domain\\ItemId;\n\nclass EquipItemCommand\n{\n    /**\n     * @var ItemId\n     */\n    private $itemId;\n    /**\n     * @var CharacterId\n     */\n    private $ownerCharacterId;\n\n    public function __construct(ItemId $itemId, CharacterId $ownerCharacterId)\n    {\n        $this->itemId = $itemId;\n        $this->ownerCharacterId = $ownerCharacterId;\n    }\n\n    public function getItemId(): ItemId\n    {\n        return $this->itemId;\n    }\n\n    public function getOwnerCharacterId(): CharacterId\n    {\n        return $this->ownerCharacterId;\n    }\n}\n"
  },
  {
    "path": "app/Modules/Equipment/Application/Contracts/InventoryRepositoryInterface.php",
    "content": "<?php\n\nnamespace App\\Modules\\Equipment\\Application\\Contracts;\n\nuse App\\Modules\\Character\\Domain\\CharacterId;\nuse App\\Modules\\Equipment\\Domain\\Inventory;\nuse App\\Modules\\Equipment\\Domain\\InventoryId;\n\ninterface InventoryRepositoryInterface\n{\n    public function nextIdentity(): InventoryId;\n\n    public function add(Inventory $inventory): void;\n\n    public function forCharacter(CharacterId $characterId): Inventory;\n\n    public function update(Inventory $inventory): void;\n}\n"
  },
  {
    "path": "app/Modules/Equipment/Application/Contracts/ItemPrototypeRepositoryInterface.php",
    "content": "<?php\n\nnamespace App\\Modules\\Equipment\\Application\\Contracts;\n\nuse App\\Modules\\Equipment\\Domain\\ItemPrototypeId;\nuse App\\Modules\\Equipment\\Domain\\ItemPrototype;\n\ninterface ItemPrototypeRepositoryInterface\n{\n    public function nextIdentity(): ItemPrototypeId;\n\n    public function getOne(ItemPrototypeId $itemPrototypeId): ItemPrototype;\n}\n"
  },
  {
    "path": "app/Modules/Equipment/Application/Contracts/ItemRepositoryInterface.php",
    "content": "<?php\n\nnamespace App\\Modules\\Equipment\\Application\\Contracts;\n\nuse App\\Modules\\Equipment\\Domain\\ItemId;\nuse App\\Modules\\Equipment\\Domain\\Item;\n\ninterface ItemRepositoryInterface\n{\n    public function nextIdentity(): ItemId;\n\n    public function add(Item $item): void;\n\n    public function getOne(ItemId $itemId): Item;\n\n    public function update(Item $item): void;\n}\n"
  },
  {
    "path": "app/Modules/Equipment/Application/Factories/ItemFactory.php",
    "content": "<?php\n\nnamespace App\\Modules\\Equipment\\Application\\Factories;\n\nuse App\\Modules\\Character\\Domain\\CharacterId;\nuse App\\Modules\\Equipment\\Domain\\Item;\nuse App\\Modules\\Equipment\\Domain\\ItemId;\nuse App\\Modules\\Equipment\\Domain\\ItemPrototype;\n\n\nclass ItemFactory\n{\n    public function create(ItemId $itemId, ItemPrototype $itemPrototype, CharacterId $creatorCharacterId): Item\n    {\n        return new Item(\n            $itemId,\n            $itemPrototype->getName(),\n            $itemPrototype->getDescription(),\n            $itemPrototype->getImageFilePath(),\n            $itemPrototype->getType(),\n            $itemPrototype->getEffects(),\n            $itemPrototype->getPrice(),\n            $itemPrototype->getId(),\n            $creatorCharacterId\n        );\n    }\n}\n"
  },
  {
    "path": "app/Modules/Equipment/Application/Services/InventoryService.php",
    "content": "<?php declare(strict_types=1);\n\n\nnamespace App\\Modules\\Equipment\\Application\\Services;\n\nuse App\\Modules\\Equipment\\Application\\Commands\\CreateInventoryCommand;\nuse App\\Modules\\Equipment\\Application\\Commands\\EquipItemCommand;\nuse App\\Modules\\Equipment\\Application\\Contracts\\InventoryRepositoryInterface;\nuse App\\Modules\\Equipment\\Domain\\Inventory;\nuse App\\Modules\\Equipment\\Domain\\Money;\nuse Illuminate\\Support\\Collection;\n\nclass InventoryService\n{\n    /**\n     * @var InventoryRepositoryInterface\n     */\n    private $inventoryRepository;\n\n    public function __construct(InventoryRepositoryInterface $inventoryRepository)\n    {\n        $this->inventoryRepository = $inventoryRepository;\n    }\n\n    public function create(CreateInventoryCommand $command):Inventory\n    {\n        $id = $this->inventoryRepository->nextIdentity();\n\n        $inventory = new Inventory($id, $command->getCharacterId(), Collection::make(), new Money(0));\n\n        $this->inventoryRepository->add($inventory);\n\n        return $inventory;\n    }\n\n    public function equipItem(EquipItemCommand $command): void\n    {\n        $inventory = $this->inventoryRepository->forCharacter($command->getOwnerCharacterId());\n\n        $inventory->equip($command->getItemId());\n\n        $this->inventoryRepository->update($inventory);\n    }\n\n    public function unEquipItem(EquipItemCommand $command): void\n    {\n        $inventory = $this->inventoryRepository->forCharacter($command->getOwnerCharacterId());\n\n        $inventory->unEquipItem($command->getItemId());\n\n        $this->inventoryRepository->update($inventory);\n    }\n}\n"
  },
  {
    "path": "app/Modules/Equipment/Application/Services/ItemService.php",
    "content": "<?php\n\nnamespace App\\Modules\\Equipment\\Application\\Services;\n\nuse App\\Modules\\Character\\Application\\Contracts\\CharacterRepositoryInterface;\nuse App\\Modules\\Equipment\\Application\\Commands\\CreateItemCommand;\nuse App\\Modules\\Equipment\\Application\\Contracts\\ItemPrototypeRepositoryInterface;\nuse App\\Modules\\Equipment\\Application\\Contracts\\ItemRepositoryInterface;\nuse App\\Modules\\Equipment\\Domain\\Item;\nuse App\\Modules\\Equipment\\Application\\Factories\\ItemFactory;\nuse Illuminate\\Support\\Facades\\DB;\nuse Illuminate\\Validation\\Concerns\\ValidatesAttributes;\n\nclass ItemService\n{\n    /**\n     * @var ItemRepositoryInterface\n     */\n    private $itemRepository;\n    /**\n     * @var ItemFactory\n     */\n    private $itemFactory;\n    /**\n     * @var ItemPrototypeRepositoryInterface\n     */\n    private $itemPrototypeRepository;\n    /**\n     * @var \\App\\Modules\\Character\\Application\\Contracts\\CharacterRepositoryInterface\n     */\n    private $characterRepository;\n\n    public function __construct(\n        CharacterRepositoryInterface $characterRepository,\n        ItemRepositoryInterface $itemRepository,\n        ItemPrototypeRepositoryInterface $itemPrototypeRepository,\n        ItemFactory $itemFactory\n    )\n    {\n        $this->characterRepository = $characterRepository;\n        $this->itemRepository = $itemRepository;\n        $this->itemPrototypeRepository = $itemPrototypeRepository;\n        $this->itemFactory = $itemFactory;\n    }\n\n    public function create(CreateItemCommand $command): void\n    {\n        DB::transaction(function () use ($command) {\n            $itemPrototype = $this->itemPrototypeRepository->getOne($command->getPrototypeId());\n            $character = $this->characterRepository->getOne($command->getCreatorCharacterId());\n            $itemId = $this->itemRepository->nextIdentity();\n\n            $item = $this->itemFactory->create($itemId, $itemPrototype, $character->getId());\n\n            $character->addItemToInventory($item);\n\n            $this->itemRepository->add($item);\n            $this->characterRepository->update($character);\n        });\n    }\n}\n"
  },
  {
    "path": "app/Modules/Equipment/Domain/Inventory.php",
    "content": "<?php\n\nnamespace App\\Modules\\Equipment\\Domain;\n\nuse App\\Modules\\Character\\Domain\\CharacterId;\nuse App\\Modules\\Generic\\Domain\\Container\\ContainerIsFullException;\nuse App\\Modules\\Generic\\Domain\\Container\\ItemNotInContainer;\nuse App\\Modules\\Generic\\Domain\\Container\\NotEnoughSpaceInContainerException;\nuse Illuminate\\Support\\Collection;\nuse InvalidArgumentException;\n\nclass Inventory\n{\n    public const NUMBER_OF_SLOTS = 24;\n\n    /**\n     * @var InventoryId\n     */\n    private $id;\n\n    /**\n     * @var CharacterId\n     */\n    private $characterId;\n\n    /**\n     * @var Collection\n     */\n    private $items;\n\n    /**\n     * @var Money\n     */\n    private $money;\n\n    public function __construct(InventoryId $id, CharacterId $characterId, Collection $items, Money $money)\n    {\n        if ($items->count() > self::NUMBER_OF_SLOTS) {\n            throw new NotEnoughSpaceInContainerException(\n                \"Not enough space in the Inventory for {$items->count()} new items\"\n            );\n        }\n\n        $items->each(static function ($item) {\n           if (!($item instanceof InventoryItem)) {\n               throw new InvalidArgumentException('Trying to populate inventory with non inventory item');\n           }\n        });\n\n        $this->id = $id;\n        $this->characterId = $characterId;\n        $this->items = $items;\n        $this->money = $money;\n    }\n\n    public function getId(): InventoryId\n    {\n        return $this->id;\n    }\n\n    public function add(Item $item): void\n    {\n        $item = new InventoryItem($item, ItemStatus::inBackpack());\n\n        $slot = $this->findFreeSlot();\n\n        $this->items->put($slot, $item);\n    }\n\n    public function getEquippedItemsEffect(string $itemEffectType): int\n    {\n        return (int)$this->getEquippedItems()->reduce(static function ($carry, InventoryItem $item) use ($itemEffectType) {\n\n            $itemEffect = $item->getItemEffect($itemEffectType);\n\n            return $carry + $itemEffect;\n        });\n    }\n\n    public function unEquipItem(ItemId $itemId): void\n    {\n        $equippedItem = $this->findEquippedItem($itemId);\n\n        if ($equippedItem)\n        {\n            $equippedItem->unEquip();\n        }\n    }\n\n    public function equip(ItemId $itemId): void\n    {\n        $item = $this->findItem($itemId);\n        if (!$item) {\n            throw new ItemNotInContainer('Cannot equip item that is not in the inventory');\n        }\n\n        if ($equippedItem = $this->findEquippedItemOfType($item->getType())) {\n            $equippedItem->unEquip();\n        }\n\n        $item->equip();\n    }\n\n    public function getCharacterId(): CharacterId\n    {\n        return $this->characterId;\n    }\n\n    public function getItems(): Collection\n    {\n        return $this->items;\n    }\n\n    public function takeOut(ItemId $itemId): Item\n    {\n        $slot = $this->items->search(static function (InventoryItem $item) use ($itemId) {\n            return $item->getId()->equals($itemId);\n        });\n\n        if ($slot === false) {\n            throw new ItemNotInContainer('Cannot take out item from empty slot');\n        }\n\n        /** @var InventoryItem $item */\n        $item = $this->items->get($slot);\n\n        $this->items->forget($slot);\n\n        return $item->toBaseItem();\n    }\n\n    public function putMoneyIn(Money $money): void\n    {\n        $this->money = $this->money->combine($money);\n    }\n\n    public function takeMoneyOut(Money $money): Money\n    {\n        $this->money = $this->money->remove($money);\n\n        return $money;\n    }\n\n    public function getMoney(): Money\n    {\n        return $this->money;\n    }\n\n    public function findItem(ItemId $itemId):? InventoryItem\n    {\n        return $this->items->first(static function (InventoryItem $item) use ($itemId) {\n            return $item->getId()->equals($itemId);\n        });\n    }\n\n    private function findFreeSlot(): int\n    {\n        for ($slot = 0; $slot < self::NUMBER_OF_SLOTS; $slot++) {\n            if (!$this->items->has($slot)) {\n                return $slot;\n            }\n        }\n\n        throw new ContainerIsFullException('Cannot add to full inventory');\n    }\n\n    private function findEquippedItem(ItemId $itemId):? InventoryItem\n    {\n        return $this->items->first(static function (InventoryItem $item) use ($itemId) {\n            return $item->getId()->equals($itemId) && $item->isEquipped();\n        });\n    }\n\n    private function findEquippedItemOfType(ItemType $type):? InventoryItem\n    {\n        return $this->items->first(static function (InventoryItem $item) use ($type) {\n            return $item->isOfType($type) && $item->isEquipped();\n        });\n    }\n\n    private function getEquippedItems(): Collection\n    {\n        return $this->items->filter(static function (InventoryItem $item) {\n            return $item->isEquipped();\n        });\n    }\n}\n"
  },
  {
    "path": "app/Modules/Equipment/Domain/InventoryId.php",
    "content": "<?php declare(strict_types=1);\n\n\nnamespace App\\Modules\\Equipment\\Domain;\n\n\nuse App\\Modules\\Generic\\Domain\\BaseId;\n\nclass InventoryId extends BaseId\n{\n}\n"
  },
  {
    "path": "app/Modules/Equipment/Domain/InventoryItem.php",
    "content": "<?php\n\nnamespace App\\Modules\\Equipment\\Domain;\n\n\nclass InventoryItem extends Item\n{\n    /**\n     * @var ItemStatus\n     */\n    private $status;\n\n    public function __construct(Item $item, ItemStatus $status)\n    {\n        parent::__construct(\n            $item->getId(),\n            $item->getName(),\n            $item->getDescription(),\n            $item->getImageFilePath(),\n            $item->getType(),\n            $item->getEffects(),\n            $item->getPrice(),\n            $item->getPrototypeId(),\n            $item->getCreatorCharacterId()\n        );\n\n        $this->status = $status;\n    }\n\n    public function getStatus(): ItemStatus\n    {\n        return $this->status;\n    }\n\n    public function isEquipped(): bool\n    {\n        return $this->status->equals(ItemStatus::equipped());\n    }\n\n    public function equip(): void\n    {\n        $this->status = ItemStatus::equipped();\n    }\n\n    public function unEquip(): void\n    {\n        $this->status = ItemStatus::inBackpack();\n    }\n}\n"
  },
  {
    "path": "app/Modules/Equipment/Domain/InventorySlot.php",
    "content": "<?php declare(strict_types=1);\n\n\nnamespace App\\Modules\\Equipment\\Domain;\n\n\nclass InventorySlot\n{\n    private $slot;\n\n    public static function undefined(): self\n    {\n        return new self(-1);\n    }\n\n    public static function defined(int $slot): self\n    {\n        return new self($slot);\n    }\n\n    public function __construct(int $slot)\n    {\n        $this->slot = $slot;\n    }\n\n    public function getSlot(): int\n    {\n        return $this->slot;\n    }\n}\n"
  },
  {
    "path": "app/Modules/Equipment/Domain/Item.php",
    "content": "<?php\n\nnamespace App\\Modules\\Equipment\\Domain;\n\n\nuse App\\Modules\\Character\\Domain\\CharacterId;\nuse Illuminate\\Support\\Collection;\n\nclass Item\n{\n    /**\n     * @var ItemId\n     */\n    private $id;\n    /**\n     * @var string\n     */\n    private $name;\n    /**\n     * @var string\n     */\n    private $description;\n    /**\n     * @var ItemType\n     */\n    private $type;\n    /**\n     * @var Collection\n     */\n    private $effects;\n    /**\n     * @var ItemPrototypeId\n     */\n    private $prototypeId;\n    /**\n     * @var CharacterId\n     */\n    private $creatorCharacterId;\n    /**\n     * @var string\n     */\n    private $imageFilePath;\n    /**\n     * @var ItemPrice\n     */\n    private $price;\n\n    public function __construct(\n        ItemId $id,\n        string $name,\n        string $description,\n        string $imageFilePath,\n        ItemType $type,\n        Collection $effects,\n        ItemPrice $price,\n        ItemPrototypeId $prototypeId,\n        CharacterId $creatorCharacterId\n    )\n    {\n        $this->id = $id;\n        $this->name = $name;\n        $this->description = $description;\n        $this->imageFilePath = $imageFilePath;\n        $this->type = $type;\n        $this->effects = $effects;\n        $this->price = $price;\n        $this->prototypeId = $prototypeId;\n        $this->creatorCharacterId = $creatorCharacterId;\n    }\n\n    public function getId(): ItemId\n    {\n        return $this->id;\n    }\n\n    public function getName(): string\n    {\n        return $this->name;\n    }\n\n    public function getDescription(): string\n    {\n        return $this->description;\n    }\n\n    public function getImageFilePath(): string\n    {\n        return $this->imageFilePath;\n    }\n\n    public function getType(): ItemType\n    {\n        return $this->type;\n    }\n\n    public function getEffects(): Collection\n    {\n        return $this->effects;\n    }\n\n    public function getPrototypeId(): ItemPrototypeId\n    {\n        return $this->prototypeId;\n    }\n\n    public function getCreatorCharacterId(): CharacterId\n    {\n        return $this->creatorCharacterId;\n    }\n\n    public function getItemEffect(string $itemEffectType): int\n    {\n        return (int)$this->getEffectsOfType($itemEffectType)\n            ->reduce(static function ($carry, ItemEffect $itemEffect) {\n                return $carry + $itemEffect->getQuantity();\n            });\n    }\n\n    private function getEffectsOfType(string $itemEffectType): Collection\n    {\n        return $this->effects->filter(static function (ItemEffect $effect) use ($itemEffectType) {\n            return $effect->getType() === $itemEffectType;\n        });\n    }\n\n    public function equals(Item $otherItem): bool\n    {\n        return $this->getId()->equals($otherItem->getId());\n    }\n\n    public function isOfType(ItemType $type): bool\n    {\n        return $this->getType()->equals($type);\n    }\n\n    public function getPrice(): ItemPrice\n    {\n        return $this->price;\n    }\n\n    public function changePrice(ItemPrice $price): self\n    {\n        $this->price = $price;\n\n        return $this;\n    }\n\n    public function toBaseItem(): Item\n    {\n        return new Item(\n            $this->getId(),\n            $this->getName(),\n            $this->getDescription(),\n            $this->getImageFilePath(),\n            $this->getType(),\n            $this->getEffects(),\n            $this->getPrice(),\n            $this->getPrototypeId(),\n            $this->getCreatorCharacterId()\n        );\n    }\n}\n"
  },
  {
    "path": "app/Modules/Equipment/Domain/ItemEffect.php",
    "content": "<?php\n\nnamespace App\\Modules\\Equipment\\Domain;\n\n\nuse InvalidArgumentException;\n\nclass ItemEffect\n{\n    public const NONE = 'none';\n    public const DAMAGE = 'damage';\n    public const ARMOR = 'armor';\n    public const PRECISION = 'precision';\n    public const EVASION = 'evasion';\n    public const TRICKERY = 'evasion';\n    public const AWARENESS = 'awareness';\n\n    public const TYPES = [\n        self::NONE,\n        self::DAMAGE,\n        self::ARMOR,\n        self::PRECISION,\n        self::EVASION,\n        self::TRICKERY,\n        self::AWARENESS,\n    ];\n\n    /**\n     * @var int\n     */\n    private $quantity;\n    /**\n     * @var string\n     */\n    private $type;\n\n    private function __construct(int $quantity, string $type)\n    {\n        $this->quantity = $quantity;\n        $this->type = $type;\n    }\n\n    public static function ofType(int $quantity, string $type): ItemEffect\n    {\n        if (!in_array($type, self::TYPES, true)) {\n            throw new InvalidArgumentException(\"$type is not a valid Item Effect type\");\n        }\n\n        return new self($quantity, $type);\n    }\n\n    public static function damage(int $quantity): ItemEffect\n    {\n        return new self($quantity, self::DAMAGE);\n    }\n\n    public static function armor(int $quantity): ItemEffect\n    {\n        return new self($quantity, self::ARMOR);\n    }\n\n    public function getQuantity(): int\n    {\n        return $this->quantity;\n    }\n\n    public function getType(): string\n    {\n        return $this->type;\n    }\n}\n"
  },
  {
    "path": "app/Modules/Equipment/Domain/ItemId.php",
    "content": "<?php declare(strict_types=1);\n\n\nnamespace App\\Modules\\Equipment\\Domain;\n\n\nuse App\\Modules\\Generic\\Domain\\BaseId;\n\nclass ItemId extends BaseId\n{\n}\n"
  },
  {
    "path": "app/Modules/Equipment/Domain/ItemPrice.php",
    "content": "<?php declare(strict_types=1);\n\n\nnamespace App\\Modules\\Equipment\\Domain;\n\n\nuse Webmozart\\Assert\\Assert;\n\nclass ItemPrice\n{\n    /**\n     * @var int\n     */\n    private $amount;\n\n    private function __construct(int $amount)\n    {\n        Assert::greaterThanEq($amount, 0, 'Item price must be greater or equal to 0');\n\n        $this->amount = $amount;\n    }\n\n    public static function ofAmount(int $amount): self\n    {\n        return new self($amount);\n    }\n\n    public function getAmount(): int\n    {\n        return $this->amount;\n    }\n}\n"
  },
  {
    "path": "app/Modules/Equipment/Domain/ItemPrototype.php",
    "content": "<?php\n\nnamespace App\\Modules\\Equipment\\Domain;\n\n\nuse Illuminate\\Support\\Collection;\n\nclass ItemPrototype\n{\n    /**\n     * @var ItemPrototypeId\n     */\n    private $id;\n    /**\n     * @var string\n     */\n    private $name;\n    /**\n     * @var string\n     */\n    private $description;\n    /**\n     * @var string\n     */\n    private $imageFilePath;\n    /**\n     * @var ItemType\n     */\n    private $type;\n    /**\n     * @var Collection\n     */\n    private $effects;\n    /**\n     * @var ItemPrice\n     */\n    private $price;\n\n    public function __construct(\n        ItemPrototypeId $id,\n        string $name,\n        string $description,\n        string $imageFilePath,\n        ItemType $type,\n        Collection $effects,\n        ItemPrice $price\n    ) {\n        $this->id = $id;\n        $this->name = $name;\n        $this->description = $description;\n        $this->imageFilePath = $imageFilePath;\n        $this->type = $type;\n        $this->effects = $effects;\n        $this->price = $price;\n    }\n\n    public function getId(): ItemPrototypeId\n    {\n        return $this->id;\n    }\n\n    public function getName(): string\n    {\n        return $this->name;\n    }\n\n    public function getDescription(): string\n    {\n        return $this->description;\n    }\n\n    public function getImageFilePath(): string\n    {\n        return $this->imageFilePath;\n    }\n\n    public function getType(): ItemType\n    {\n        return $this->type;\n    }\n\n    public function getEffects(): Collection\n    {\n        return $this->effects;\n    }\n\n    public function getPrice(): ItemPrice\n    {\n        return $this->price;\n    }\n}\n"
  },
  {
    "path": "app/Modules/Equipment/Domain/ItemPrototypeId.php",
    "content": "<?php declare(strict_types=1);\n\n\nnamespace App\\Modules\\Equipment\\Domain;\n\n\nuse App\\Modules\\Generic\\Domain\\BaseId;\n\nclass ItemPrototypeId extends BaseId\n{\n}\n"
  },
  {
    "path": "app/Modules/Equipment/Domain/ItemStatus.php",
    "content": "<?php\n\nnamespace App\\Modules\\Equipment\\Domain;\n\nuse InvalidArgumentException;\n\nclass ItemStatus\n{\n    public const EQUIPPED = 'equipped';\n    public const IN_BACKPACK = 'in_backpack';\n\n    public const STATUSES = [\n        self::EQUIPPED,\n        self::IN_BACKPACK,\n    ];\n\n    /**\n     * @var string\n     */\n    private $type;\n\n    private function __construct(string $type)\n    {\n        $this->type = $type;\n    }\n\n    public static function ofStatus(string $status): self\n    {\n        if (!in_array($status, self::STATUSES, true)) {\n            throw new InvalidArgumentException(\"$status is not a valid Item Status\");\n        }\n\n        return new self($status);\n    }\n\n    public static function inBackpack(): self\n    {\n        return new self(self::IN_BACKPACK);\n    }\n\n    public static function equipped(): self\n    {\n        return new self(self::EQUIPPED);\n    }\n\n    public function toString(): string\n    {\n        return $this->type;\n    }\n\n    public function equals(self $type): bool\n    {\n        return $this->type === $type->toString();\n    }\n}\n"
  },
  {
    "path": "app/Modules/Equipment/Domain/ItemType.php",
    "content": "<?php\n\nnamespace App\\Modules\\Equipment\\Domain;\n\nuse InvalidArgumentException;\n\nclass ItemType\n{\n    public const MISCELLANEOUS = 'miscellaneous';\n    public const HEAD_GEAR = 'head_gear';\n    public const BODY_ARMOR = 'body_armor';\n    public const MAIN_HAND = 'main_hand';\n    public const OFF_HAND = 'off_hand';\n\n    public const TYPES = [\n        self::MISCELLANEOUS,\n        self::HEAD_GEAR,\n        self::BODY_ARMOR,\n        self::MAIN_HAND,\n        self::OFF_HAND,\n    ];\n\n    /**\n     * @var string\n     */\n    private $type;\n\n    private function __construct(string $type)\n    {\n        $this->type = $type;\n    }\n\n    public static function ofType(string $type): ItemType\n    {\n        if (!in_array($type, self::TYPES, true)) {\n            throw new InvalidArgumentException(\"$type is not a valid Item Type\");\n        }\n\n        return new self($type);\n    }\n\n    public static function headGear(): ItemType\n    {\n        return new self(self::HEAD_GEAR);\n    }\n\n    public static function bodyArmor(): ItemType\n    {\n        return new self(self::BODY_ARMOR);\n    }\n\n    public static function mainHand(): ItemType\n    {\n        return new self(self::MAIN_HAND);\n    }\n\n    public static function offHand(): ItemType\n    {\n        return new self(self::OFF_HAND);\n    }\n\n    public function toString(): string\n    {\n        return $this->type;\n    }\n\n    public function equals(ItemType $type): bool\n    {\n        return $this->type === $type->toString();\n    }\n}\n"
  },
  {
    "path": "app/Modules/Equipment/Domain/Money.php",
    "content": "<?php declare(strict_types=1);\n\n\nnamespace App\\Modules\\Equipment\\Domain;\n\n\nuse App\\Modules\\Generic\\Domain\\Container\\InvalidMoneyValue;\nuse App\\Modules\\Generic\\Domain\\Container\\NotEnoughMoneyToRemove;\n\nclass Money\n{\n    /**\n     * @var int\n     */\n    private $value;\n\n    public function __construct(int $value)\n    {\n        if ($value < 0)\n        {\n           throw new InvalidMoneyValue('Negative money amount not allowed');\n        }\n\n        $this->value = $value;\n    }\n\n    public function getValue(): int\n    {\n        return $this->value;\n    }\n\n    public function remove(Money $money): self\n    {\n        if ($this->value < $money->getValue()) {\n            throw new NotEnoughMoneyToRemove('Cannot remove more money than there is');\n        }\n\n        return new self($this->value - $money->getValue());\n    }\n\n    public function combine(Money $money): self\n    {\n        return new self($this->value + $money->getValue());\n    }\n}\n"
  },
  {
    "path": "app/Modules/Equipment/Infrastructure/ReconstitutionFactories/InventoryItemReconstitutionFactory.php",
    "content": "<?php\n\n\nnamespace App\\Modules\\Equipment\\Infrastructure\\ReconstitutionFactories;\n\nuse App\\Models\\Item as ItemModel;\nuse App\\Modules\\Equipment\\Domain\\InventoryItem;\nuse App\\Modules\\Equipment\\Domain\\ItemStatus;\n\n\nclass InventoryItemReconstitutionFactory\n{\n    /**\n     * @var ItemReconstitutionFactory\n     */\n    private $itemReconstitutionFactory;\n\n    public function __construct(ItemReconstitutionFactory $itemReconstitutionFactory)\n    {\n        $this->itemReconstitutionFactory = $itemReconstitutionFactory;\n    }\n\n    public function reconstitute(ItemModel $model): InventoryItem\n    {\n        return new InventoryItem(\n            $this->itemReconstitutionFactory->reconstitute($model),\n            ItemStatus::ofStatus($model->pivot->status)\n        );\n    }\n}\n"
  },
  {
    "path": "app/Modules/Equipment/Infrastructure/ReconstitutionFactories/InventoryReconstitutionFactory.php",
    "content": "<?php\n\n\nnamespace App\\Modules\\Equipment\\Infrastructure\\ReconstitutionFactories;\n\nuse App\\Models\\Item as ItemModel;\nuse App\\Models\\Inventory as InventoryModel;\nuse App\\Modules\\Character\\Domain\\CharacterId;\nuse App\\Modules\\Equipment\\Domain\\Inventory;\nuse App\\Modules\\Equipment\\Domain\\InventoryId;\nuse App\\Modules\\Equipment\\Domain\\Money;\n\nclass InventoryReconstitutionFactory\n{\n    /**\n     * @var InventoryItemReconstitutionFactory\n     */\n    private $inventoryItemReconstitutionFactory;\n\n    public function __construct(InventoryItemReconstitutionFactory $inventoryItemReconstitutionFactory)\n    {\n        $this->inventoryItemReconstitutionFactory = $inventoryItemReconstitutionFactory;\n    }\n\n    public function reconstitute(InventoryModel $inventoryModel): Inventory\n    {\n        $items = $inventoryModel->items->mapWithKeys(function (ItemModel $itemModel) {\n\n            $key = $itemModel->getInventorySlotNumber();\n            $inventoryItem = $this->inventoryItemReconstitutionFactory->reconstitute($itemModel);\n\n            return [$key => $inventoryItem];\n        });\n\n        return new Inventory(\n            InventoryId::fromString($inventoryModel->getId()),\n            CharacterId::fromString($inventoryModel->getCharacterId()),\n            $items,\n            new Money($inventoryModel->getMoney())\n        );\n    }\n}\n"
  },
  {
    "path": "app/Modules/Equipment/Infrastructure/ReconstitutionFactories/ItemPrototypeReconstitutionFactory.php",
    "content": "<?php\n\n\nnamespace App\\Modules\\Equipment\\Infrastructure\\ReconstitutionFactories;\n\nuse App\\Models\\ItemPrototype as ItemPrototypeModel;\nuse App\\Modules\\Equipment\\Domain\\ItemPrice;\nuse App\\Modules\\Equipment\\Domain\\ItemPrototype;\nuse App\\Modules\\Equipment\\Domain\\ItemEffect;\nuse App\\Modules\\Equipment\\Domain\\ItemPrototypeId;\nuse App\\Modules\\Equipment\\Domain\\ItemType;\nuse Illuminate\\Support\\Collection;\n\n\nclass ItemPrototypeReconstitutionFactory\n{\n    public function reconstitute(ItemPrototypeModel $model): ItemPrototype\n    {\n        $effects = Collection::make($model->getEffects())->map(static function (array $effect) {\n                return ItemEffect::ofType(\n                    $effect['quantity'],\n                    $effect['type']);\n            });\n\n        $itemPrototype = new ItemPrototype(\n            ItemPrototypeId::fromString($model->getId()),\n            $model->getName(),\n            $model->getDescription(),\n            $model->getImageFilePath(),\n            ItemType::ofType($model->getType()),\n            $effects,\n            ItemPrice::ofAmount($model->getPrice())\n        );\n\n        return $itemPrototype;\n    }\n}\n"
  },
  {
    "path": "app/Modules/Equipment/Infrastructure/ReconstitutionFactories/ItemReconstitutionFactory.php",
    "content": "<?php\n\n\nnamespace App\\Modules\\Equipment\\Infrastructure\\ReconstitutionFactories;\n\nuse App\\Models\\Item as ItemModel;\nuse App\\Modules\\Character\\Domain\\CharacterId;\nuse App\\Modules\\Equipment\\Domain\\Item;\nuse App\\Modules\\Equipment\\Domain\\ItemEffect;\nuse App\\Modules\\Equipment\\Domain\\ItemId;\nuse App\\Modules\\Equipment\\Domain\\ItemPrice;\nuse App\\Modules\\Equipment\\Domain\\ItemPrototypeId;\nuse App\\Modules\\Equipment\\Domain\\ItemType;\nuse Illuminate\\Support\\Collection;\n\n\nclass ItemReconstitutionFactory\n{\n    public function reconstitute(ItemModel $model): Item\n    {\n        $effects = Collection::make($model->getEffects())->map(static function (array $effect) {\n            return ItemEffect::ofType(\n                $effect['quantity'],\n                $effect['type']\n            );\n        });\n\n        $item = new Item(\n            ItemId::fromString($model->getId()),\n            $model->getName(),\n            $model->getDescription(),\n            $model->getImageFilePath(),\n            ItemType::ofType($model->getType()),\n            $effects,\n            ItemPrice::ofAmount($model->getPrice()),\n            ItemPrototypeId::fromString($model->getPrototypeId()),\n            CharacterId::fromString($model->getCreatorCharacterId())\n        );\n\n        return $item;\n    }\n}\n"
  },
  {
    "path": "app/Modules/Equipment/Infrastructure/Repositories/InventoryRepository.php",
    "content": "<?php\n\nnamespace App\\Modules\\Equipment\\Infrastructure\\Repositories;\n\nuse App\\Models\\Inventory as InventoryModel;\nuse App\\Modules\\Character\\Domain\\CharacterId;\nuse App\\Modules\\Equipment\\Application\\Contracts\\InventoryRepositoryInterface;\nuse App\\Modules\\Equipment\\Domain\\Inventory;\nuse App\\Modules\\Equipment\\Domain\\InventoryId;\nuse App\\Modules\\Equipment\\Domain\\InventoryItem;\nuse App\\Modules\\Equipment\\Infrastructure\\ReconstitutionFactories\\InventoryReconstitutionFactory;\nuse App\\Traits\\GeneratesUuid;\nuse Exception;\n\nclass InventoryRepository implements InventoryRepositoryInterface\n{\n    use GeneratesUuid;\n\n    /**\n     * @var InventoryReconstitutionFactory\n     */\n    private $reconstitutionFactory;\n\n    public function __construct(InventoryReconstitutionFactory $reconstitutionFactory)\n    {\n        $this->reconstitutionFactory = $reconstitutionFactory;\n    }\n\n    /**\n     * @return InventoryId\n     *\n     * @throws Exception\n     */\n    public function nextIdentity(): InventoryId\n    {\n        return InventoryId::fromString($this->generateUuid());\n    }\n\n    public function add(Inventory $inventory): void\n    {\n        InventoryModel::query()->create([\n            'id' => $inventory->getId()->toString(),\n            'character_id' => $inventory->getCharacterId()->toString(),\n            'money' => $inventory->getMoney()->getValue(),\n        ]);\n    }\n\n    public function forCharacter(CharacterId $characterId): Inventory\n    {\n        /** @var InventoryModel $model */\n        $model = InventoryModel::query()->where('character_id', $characterId->toString())->firstOrFail();\n\n        return $this->reconstitutionFactory->reconstitute($model);\n    }\n\n    public function update(Inventory $inventory): void\n    {\n        /** @var InventoryModel $inventoryModel */\n        $inventoryModel = InventoryModel::query()->findOrFail($inventory->getId()->toString());\n\n        $inventoryItems = $inventory->getItems()->mapWithKeys(static function (InventoryItem $item, int $slot) {\n            $itemId = $item->getId()->toString();\n\n            return [\n                $itemId => [\n                    'item_id' => $itemId,\n                    'status' => $item->getStatus()->toString(),\n                    'inventory_slot_number' => $slot,\n                ],\n            ];\n        });\n\n         $inventoryModel->items()->sync($inventoryItems->all());\n\n         $inventoryModel->update([\n             'money' => $inventory->getMoney()->getValue(),\n         ]);\n    }\n}\n"
  },
  {
    "path": "app/Modules/Equipment/Infrastructure/Repositories/ItemPrototypeRepository.php",
    "content": "<?php\n\nnamespace App\\Modules\\Equipment\\Infrastructure\\Repositories;\n\nuse App\\Models\\ItemPrototype as ItemPrototypeModel;\nuse App\\Modules\\Equipment\\Domain\\ItemPrototypeId;\nuse App\\Modules\\Equipment\\Application\\Contracts\\ItemPrototypeRepositoryInterface;\nuse App\\Modules\\Equipment\\Domain\\ItemPrototype;\nuse App\\Modules\\Equipment\\Infrastructure\\ReconstitutionFactories\\ItemPrototypeReconstitutionFactory;\nuse App\\Traits\\GeneratesUuid;\nuse Exception;\n\nclass ItemPrototypeRepository implements ItemPrototypeRepositoryInterface\n{\n    use GeneratesUuid;\n\n    /**\n     * @var ItemPrototypeReconstitutionFactory\n     */\n    private $reconstitutionFactory;\n\n    public function __construct(ItemPrototypeReconstitutionFactory $reconstitutionFactory)\n    {\n        $this->reconstitutionFactory = $reconstitutionFactory;\n    }\n\n    /**\n     * @return ItemPrototypeId\n     *\n     * @throws Exception\n     */\n    public function nextIdentity(): ItemPrototypeId\n    {\n        return ItemPrototypeId::fromString($this->generateUuid());\n    }\n\n    public function getOne(ItemPrototypeId $itemPrototypeId): ItemPrototype\n    {\n        /** @var \\App\\Models\\ItemPrototypeModel $model */\n        $model = ItemPrototypeModel::query()->findOrFail($itemPrototypeId->toString());\n\n        return $this->reconstitutionFactory->reconstitute($model);\n    }\n}\n"
  },
  {
    "path": "app/Modules/Equipment/Infrastructure/Repositories/ItemRepository.php",
    "content": "<?php\n\nnamespace App\\Modules\\Equipment\\Infrastructure\\Repositories;\n\nuse App\\Models\\Item as ItemModel;\nuse App\\Modules\\Equipment\\Domain\\ItemId;\nuse App\\Modules\\Equipment\\Application\\Contracts\\ItemRepositoryInterface;\nuse App\\Modules\\Equipment\\Domain\\Item;\nuse App\\Modules\\Equipment\\Domain\\ItemEffect;\nuse App\\Modules\\Equipment\\Infrastructure\\ReconstitutionFactories\\ItemReconstitutionFactory;\nuse App\\Traits\\GeneratesUuid;\nuse Exception;\n\nclass ItemRepository implements ItemRepositoryInterface\n{\n    use GeneratesUuid;\n\n    /**\n     * @var ItemReconstitutionFactory\n     */\n    private $reconstitutionFactory;\n\n    public function __construct(ItemReconstitutionFactory $reconstitutionFactory)\n    {\n        $this->reconstitutionFactory = $reconstitutionFactory;\n    }\n\n    /**\n     * @return ItemId\n     *\n     * @throws Exception\n     */\n    public function nextIdentity(): ItemId\n    {\n        return ItemId::fromString($this->generateUuid());\n    }\n\n    public function add(Item $item): void\n    {\n        $effects = $item->getEffects()->map(static function (ItemEffect $effect) {\n            return [\n                'quantity' => $effect->getQuantity(),\n                'type' => $effect->getType(),\n            ];\n        })->toJson();\n\n        ItemModel::query()->create([\n            'id' => $item->getId()->toString(),\n\n            'prototype_id' => $item->getPrototypeId()->toString(),\n            'creator_character_id' => $item->getCreatorCharacterId()->toString(),\n\n            'name' => $item->getName(),\n            'description' => $item->getDescription(),\n\n            'effects' => $effects,\n\n            'price' => $item->getPrice()->getAmount(),\n\n            'image_file_path' => $item->getImageFilePath(),\n\n            'type' => $item->getType()->toString(),\n        ]);\n    }\n\n    public function getOne(ItemId $itemId): Item\n    {\n        /** @var ItemModel $model */\n        $model = ItemModel::query()->findOrFail($itemId->toString());\n\n        return $this->reconstitutionFactory->reconstitute($model);\n    }\n\n    public function update(Item $item): void\n    {\n        $effects = $item->getEffects()->map(static function (ItemEffect $effect) {\n            return [\n                'quantity' => $effect->getQuantity(),\n                'type' => $effect->getType(),\n            ];\n        })->toJson();\n\n        ItemModel::query()->where('id', $item->getId()->toString())->update([\n            'prototype_id' => $item->getPrototypeId()->toString(),\n            'creator_character_id' => $item->getCreatorCharacterId()->toString(),\n\n            'name' => $item->getName(),\n            'description' => $item->getDescription(),\n\n            'effects' => $effects,\n\n            'price' => $item->getPrice()->getAmount(),\n\n            'image_file_path' => $item->getImageFilePath(),\n\n            'type' => $item->getType()->toString(),\n        ]);\n    }\n}\n"
  },
  {
    "path": "app/Modules/Equipment/UI/Http/CommandMappers/AddItemToInventoryCommandMapper.php",
    "content": "<?php\n\nnamespace App\\Modules\\Equipment\\UI\\Http\\CommandMappers;\n\nuse App\\Modules\\Character\\Domain\\CharacterId;\nuse App\\Modules\\Equipment\\Domain\\ItemId;\nuse App\\Modules\\Equipment\\Application\\Commands\\AddItemToInventoryCommand;\nuse Illuminate\\Http\\Request;\nuse App\\Models\\User as UserModel;\n\nclass AddItemToInventoryCommandMapper\n{\n    public function map(Request $request): AddItemToInventoryCommand\n    {\n        /** @var UserModel $userModel */\n        $userModel = $request->user();\n\n        return new AddItemToInventoryCommand(\n            CharacterId::fromString($userModel->character->getId()),\n            (int)$request->input('inventory_slot'),\n            ItemId::fromString((string)$request->input('item_id'))\n        );\n    }\n}\n"
  },
  {
    "path": "app/Modules/Equipment/UI/Http/CommandMappers/CreateItemCommandMapper.php",
    "content": "<?php\n\nnamespace App\\Modules\\Equipment\\UI\\Http\\CommandMappers;\n\nuse App\\Modules\\Character\\Domain\\CharacterId;\nuse App\\Modules\\Equipment\\Domain\\ItemPrototypeId;\nuse App\\Modules\\Equipment\\Application\\Commands\\CreateItemCommand;\nuse Illuminate\\Http\\Request;\nuse App\\Models\\User as UserModel;\n\nclass CreateItemCommandMapper\n{\n    public function map(Request $request): CreateItemCommand\n    {\n        /** @var UserModel $userModel */\n        $userModel = $request->user();\n\n        return new CreateItemCommand(\n            ItemPrototypeId::fromString($request->input('prototype_item_id')),\n            CharacterId::fromString($userModel->character->getId())\n        );\n    }\n}\n"
  },
  {
    "path": "app/Modules/Equipment/UI/Http/CommandMappers/EquipItemCommandMapper.php",
    "content": "<?php\n\nnamespace App\\Modules\\Equipment\\UI\\Http\\CommandMappers;\n\nuse App\\Modules\\Character\\Domain\\CharacterId;\nuse App\\Modules\\Equipment\\Domain\\ItemId;\nuse App\\Modules\\Equipment\\Application\\Commands\\EquipItemCommand;\nuse Illuminate\\Http\\Request;\nuse App\\Models\\User as UserModel;\n\nclass EquipItemCommandMapper\n{\n    public function map(Request $request): EquipItemCommand\n    {\n        /** @var UserModel $userModel */\n        $userModel = $request->user();\n\n        return new EquipItemCommand(\n            ItemId::fromString((string)$request->route('item')),\n            CharacterId::fromString($userModel->character->getId())\n        );\n    }\n}\n"
  },
  {
    "path": "app/Modules/Generic/Domain/BaseId.php",
    "content": "<?php declare(strict_types=1);\n\nnamespace App\\Modules\\Generic\\Domain;\n\nabstract class BaseId\n{\n    /**\n     * @var string\n     */\n    private $id;\n\n    private function __construct(string $id)\n    {\n        $this->id = $id;\n    }\n\n    /**\n     * @param string $id\n     *\n     * @return static\n     */\n    public static function fromString(string $id)\n    {\n        return new static($id);\n    }\n\n    public function toString(): string\n    {\n        return $this->id;\n    }\n\n    public function equals(BaseId $otherId): bool\n    {\n        return $this->toString() === $otherId->toString();\n    }\n}\n"
  },
  {
    "path": "app/Modules/Generic/Domain/Container/ContainerIsFullException.php",
    "content": "<?php\n\nnamespace App\\Modules\\Generic\\Domain\\Container;\n\nuse RuntimeException;\n\nclass ContainerIsFullException extends RuntimeException\n{\n}\n"
  },
  {
    "path": "app/Modules/Generic/Domain/Container/ContainerSlotIsTakenException.php",
    "content": "<?php\n\nnamespace App\\Modules\\Generic\\Domain\\Container;\n\nuse RuntimeException;\n\nclass ContainerSlotIsTakenException extends RuntimeException\n{\n}\n"
  },
  {
    "path": "app/Modules/Generic/Domain/Container/ContainerSlotOutOfRangeException.php",
    "content": "<?php\n\nnamespace App\\Modules\\Generic\\Domain\\Container;\n\nuse RuntimeException;\n\nclass ContainerSlotOutOfRangeException extends RuntimeException\n{\n}\n"
  },
  {
    "path": "app/Modules/Generic/Domain/Container/InvalidMoneyValue.php",
    "content": "<?php declare(strict_types=1);\n\n\nnamespace App\\Modules\\Generic\\Domain\\Container;\n\nuse RuntimeException;\n\nclass InvalidMoneyValue extends RuntimeException\n{\n}\n"
  },
  {
    "path": "app/Modules/Generic/Domain/Container/ItemNotInContainer.php",
    "content": "<?php declare(strict_types=1);\n\n\nnamespace App\\Modules\\Generic\\Domain\\Container;\n\nuse RuntimeException;\n\nclass ItemNotInContainer extends RuntimeException\n{\n}\n"
  },
  {
    "path": "app/Modules/Generic/Domain/Container/NotEnoughMoneyToRemove.php",
    "content": "<?php declare(strict_types=1);\n\n\nnamespace App\\Modules\\Generic\\Domain\\Container;\n\nuse RuntimeException;\n\nclass NotEnoughMoneyToRemove extends RuntimeException\n{\n}\n"
  },
  {
    "path": "app/Modules/Generic/Domain/Container/NotEnoughSpaceInContainerException.php",
    "content": "<?php\n\nnamespace App\\Modules\\Generic\\Domain\\Container;\n\nuse RuntimeException;\n\nclass NotEnoughSpaceInContainerException extends RuntimeException\n{\n}\n"
  },
  {
    "path": "app/Modules/Generic/Domain/Container.php",
    "content": "<?php declare(strict_types=1);\n\n\nnamespace App\\Modules\\Generic\\Domain;\n\n\nuse Illuminate\\Support\\Collection;\n\nabstract class Container\n{\n\n    /**\n     * @var Collection\n     */\n    protected $items;\n}\n"
  },
  {
    "path": "app/Modules/Generic/Domain/ContainerType.php",
    "content": "<?php declare(strict_types=1);\n\n\nnamespace App\\Modules\\Generic\\Domain;\n\n\nuse InvalidArgumentException;\n\nclass ContainerType\n{\n    private const VALID_TYPES = [\n        self::INVENTORY,\n        self::STORE\n    ];\n\n    private const INVENTORY = 'inventory';\n    private const STORE = 'store';\n\n    /**\n     * @var string\n     */\n    private $type;\n\n    public static function fromString(string $type)\n    {\n        return new static($type);\n    }\n\n    private function __construct(string $type)\n    {\n        if (!in_array($type, self::VALID_TYPES, true)) {\n            throw new InvalidArgumentException('Invalid showContainer type: ' . $type);\n        }\n\n        $this->type = $type;\n    }\n\n    public function getType(): string\n    {\n        return $this->type;\n    }\n\n    public function isStore(): bool\n    {\n        return $this->type === self::STORE;\n    }\n}\n"
  },
  {
    "path": "app/Modules/Image/Application/Commands/AddImageCommand.php",
    "content": "<?php\n\n\nnamespace App\\Modules\\Image\\Application\\Commands;\n\nuse App\\Modules\\Character\\Domain\\CharacterId;\nuse Illuminate\\Http\\UploadedFile;\n\nclass AddImageCommand\n{\n    /**\n     * @var CharacterId\n     */\n    private $characterId;\n\n    /**\n     * @var UploadedFile\n     */\n    private $uploadedFile;\n\n    public function __construct(CharacterId $characterId, UploadedFile $uploadedFile)\n    {\n        $this->characterId = $characterId;\n        $this->uploadedFile = $uploadedFile;\n    }\n\n    public function getCharacterId(): CharacterId\n    {\n        return $this->characterId;\n    }\n\n    public function getUploadedFile(): UploadedFile\n    {\n        return $this->uploadedFile;\n    }\n}\n"
  },
  {
    "path": "app/Modules/Image/Application/Contracts/ImageRepositoryInterface.php",
    "content": "<?php\n\n\nnamespace App\\Modules\\Image\\Application\\Contracts;\n\n\nuse App\\Modules\\Character\\Domain\\CharacterId;\nuse App\\Modules\\Image\\Domain\\Image;\nuse App\\Modules\\Image\\Domain\\ImageId;\nuse Illuminate\\Http\\UploadedFile;\n\ninterface ImageRepositoryInterface\n{\n    public function nextIdentity(): ImageId;\n\n    public function add(Image $image, UploadedFile $uploadedFile): void;\n\n    public function delete(CharacterId $characterId): void;\n}\n"
  },
  {
    "path": "app/Modules/Image/Application/Factories/ImageFactory.php",
    "content": "<?php\n\n\nnamespace App\\Modules\\Image\\Application\\Factories;\n\n\nuse App\\Modules\\Character\\Domain\\CharacterId;\nuse App\\Modules\\Image\\Domain\\ImageFile;\nuse App\\Modules\\Image\\Domain\\Image;\nuse App\\Modules\\Image\\Domain\\ImageId;\n\nclass ImageFactory\n{\n    public function create(ImageId $imageId, CharacterId $characterId, string $extension): Image\n    {\n        $fileName = $imageId->toString() . '.' . $extension;\n\n        return new Image(\n            $imageId,\n            $characterId,\n            ImageFile::full('full_' . $fileName),\n            ImageFile::small('small_' . $fileName),\n            ImageFile::icon('icon_' . $fileName)\n        );\n    }\n}\n"
  },
  {
    "path": "app/Modules/Image/Application/Services/ProfilePictureService.php",
    "content": "<?php\n\n\nnamespace App\\Modules\\Image\\Application\\Services;\n\nuse App\\Modules\\Character\\Application\\Services\\CharacterService;\nuse App\\Modules\\Character\\Domain\\CharacterId;\nuse App\\Modules\\Image\\Application\\Contracts\\ImageRepositoryInterface;\nuse App\\Modules\\Image\\Application\\Factories\\ImageFactory;\nuse App\\Modules\\Image\\Application\\Commands\\AddImageCommand;\n\nclass ProfilePictureService\n{\n    /**\n     * @var ImageFactory\n     */\n    private $imageFactory;\n    /**\n     * @var ImageRepositoryInterface\n     */\n    private $imageRepository;\n    /**\n     * @var CharacterService\n     */\n    private $characterService;\n\n    public function __construct(\n        ImageFactory $imageFactory,\n        ImageRepositoryInterface $imageRepository,\n        CharacterService $characterService\n    ) {\n        $this->imageFactory = $imageFactory;\n        $this->imageRepository = $imageRepository;\n        $this->characterService = $characterService;\n    }\n\n    public function update(AddImageCommand $command): void\n    {\n        $imageId = $this->imageRepository->nextIdentity();\n\n        $profilePicture = $this->imageFactory->create(\n            $imageId,\n            $command->getCharacterId(),\n            $command->getUploadedFile()->getClientOriginalExtension()\n        );\n\n        $this->imageRepository->delete($command->getCharacterId());\n\n        $this->imageRepository->add($profilePicture, $command->getUploadedFile());\n\n        $this->characterService->updateProfilePicture($profilePicture);\n    }\n\n    public function delete(CharacterId $characterId): void\n    {\n        $this->imageRepository->delete($characterId);\n\n        $this->characterService->removeProfilePicture($characterId);\n    }\n}\n"
  },
  {
    "path": "app/Modules/Image/Domain/Image.php",
    "content": "<?php\n\nnamespace App\\Modules\\Image\\Domain;\n\nuse App\\Modules\\Character\\Domain\\CharacterId;\n\nclass Image\n{\n    /**\n     * @var ImageId\n     */\n    private $id;\n    /**\n     * @var CharacterId\n     */\n    private $characterId;\n    /**\n     * @var ImageFile\n     */\n    private $fullSizeFile;\n    /**\n     * @var ImageFile\n     */\n    private $smallSizeFile;\n    /**\n     * @var ImageFile\n     */\n    private $iconSizeFile;\n\n    public function __construct(\n        ImageId $id,\n        CharacterId $characterId,\n        ImageFile $fullSizeFile,\n        ImageFile $smallSizeFile,\n        ImageFile $iconSizeFile\n    ) {\n        $this->id = $id;\n        $this->characterId = $characterId;\n        $this->fullSizeFile = $fullSizeFile;\n        $this->smallSizeFile = $smallSizeFile;\n        $this->iconSizeFile = $iconSizeFile;\n    }\n\n    public function getId(): ImageId\n    {\n        return $this->id;\n    }\n\n    public function getCharacterId(): CharacterId\n    {\n        return $this->characterId;\n    }\n\n    public function getFullSizeFile(): ImageFile\n    {\n        return $this->fullSizeFile;\n    }\n\n    public function getSmallSizeFile(): ImageFile\n    {\n        return $this->smallSizeFile;\n    }\n\n    public function getIconSizeFile(): ImageFile\n    {\n        return $this->iconSizeFile;\n    }\n}\n"
  },
  {
    "path": "app/Modules/Image/Domain/ImageFile.php",
    "content": "<?php\n\n\nnamespace App\\Modules\\Image\\Domain;\n\nclass ImageFile\n{\n    public const IMAGE_WIDTH_FULL = 1000;\n    public const IMAGE_WIDTH_SMALL = 100;\n    public const IMAGE_WIDTH_ICON = 20;\n\n    /**\n     * @var string\n     */\n    private $fileName;\n    /**\n     * @var int\n     */\n    private $width;\n\n    private function __construct(string $fileName, int $width)\n    {\n        $this->fileName = $fileName;\n        $this->width = $width;\n    }\n\n    public static function full(string $fileName): self\n    {\n        return new self($fileName, self::IMAGE_WIDTH_FULL);\n    }\n\n    public static function small(string $fileName): self\n    {\n        return new self($fileName, self::IMAGE_WIDTH_SMALL);\n    }\n\n    public static function icon(string $fileName): self\n    {\n        return new self($fileName, self::IMAGE_WIDTH_ICON);\n    }\n\n    public function getFileName(): string\n    {\n        return $this->fileName;\n    }\n\n    public function getWidth(): int\n    {\n        return $this->width;\n    }\n}\n"
  },
  {
    "path": "app/Modules/Image/Domain/ImageId.php",
    "content": "<?php declare(strict_types=1);\n\n\nnamespace App\\Modules\\Image\\Domain;\n\n\nuse App\\Modules\\Generic\\Domain\\BaseId;\n\nclass ImageId extends BaseId\n{\n}\n"
  },
  {
    "path": "app/Modules/Image/Infrastructure/Repositories/ImageRepository.php",
    "content": "<?php\n\nnamespace App\\Modules\\Image\\Infrastructure\\Repositories;\n\nuse App\\Modules\\Character\\Domain\\CharacterId;\nuse App\\Modules\\Image\\Domain\\ImageFile;\nuse App\\Modules\\Image\\Domain\\Image;\nuse App\\Models\\Image as ImageModel;\nuse App\\Modules\\Image\\Application\\Contracts\\ImageRepositoryInterface;\nuse App\\Modules\\Image\\Domain\\ImageId;\nuse App\\Traits\\GeneratesUuid;\nuse Exception;\nuse Illuminate\\Filesystem\\Filesystem;\nuse Illuminate\\Http\\UploadedFile;\nuse Intervention\\Image\\Constraint;\nuse Intervention\\Image\\ImageManager;\nuse Intervention\\Image\\Image as ImageManagerFile;\n\nclass ImageRepository implements ImageRepositoryInterface\n{\n    use GeneratesUuid;\n\n    /**\n     * @var Filesystem\n     */\n    private $filesystem;\n    /**\n     * @var ImageManager\n     */\n    private $imageManager;\n\n    public function __construct(Filesystem $filesystem, ImageManager $imageManager)\n    {\n        $this->filesystem = $filesystem;\n        $this->imageManager = $imageManager;\n    }\n\n    /**\n     * @return ImageId\n     *\n     * @throws Exception\n     */\n    public function nextIdentity(): ImageId\n    {\n        return ImageId::fromString($this->generateUuid());\n    }\n\n    public function add(Image $image, UploadedFile $uploadedFile): void\n    {\n        $urlPath = $this->getUrlPath($image->getCharacterId());\n\n        $this->writeFiles($image, $uploadedFile);\n\n        ImageModel::query()->create([\n            'id' => $image->getId()->toString(),\n            'character_id' => $image->getCharacterId()->toString(),\n            'file_path_full' => $urlPath . $image->getFullSizeFile()->getFileName(),\n            'file_path_small' => $urlPath . $image->getSmallSizeFile()->getFileName(),\n            'file_path_icon' => $urlPath . $image->getIconSizeFile()->getFileName(),\n        ]);\n    }\n\n    public function delete(CharacterId $characterId): void\n    {\n        $this->filesystem->deleteDirectory($this->getFolderPath($characterId));\n\n        ImageModel::query()->where('character_id', '=', $characterId->toString())->delete();\n    }\n\n    private function writeFiles(Image $image, UploadedFile $uploadedFile): void\n    {\n        $folderPath = $this->getFolderPath($image->getCharacterId());\n\n        $this->createFolderIfMissing($folderPath);\n\n        $imageFile = $this->imageManager->make($uploadedFile);\n\n        $this->writeFile($image->getFullSizeFile(), $folderPath, $imageFile);\n        $this->writeFile($image->getSmallSizeFile(), $folderPath, $imageFile);\n        $this->writeFile($image->getIconSizeFile(), $folderPath, $imageFile);\n    }\n\n    private function writeFile(\n        ImageFile $imageFile,\n        string $folderPath,\n        ImageManagerFile $imageManagerFile\n    ): string\n    {\n        $filePath = $folderPath . $imageFile->getFileName();\n\n        $imageManagerFile\n            ->resize($imageFile->getWidth(), null, static function (Constraint $constraint) {\n                $constraint->aspectRatio();\n            })\n            ->save($filePath);\n\n        return $filePath;\n    }\n\n    private function createFolderIfMissing(string $fullFolderPath): bool\n    {\n        return $this->filesystem->exists($fullFolderPath)\n            or $this->filesystem->makeDirectory($fullFolderPath, 0755, true);\n    }\n\n    private function getFolderPath(CharacterId $characterId): string\n    {\n        return storage_path(\n            'app' . DIRECTORY_SEPARATOR\n            . 'public' . DIRECTORY_SEPARATOR\n            . $this->getCharacterImageFolder($characterId)\n        );\n    }\n\n    private function getUrlPath(CharacterId $characterId): string\n    {\n        return 'storage' . DIRECTORY_SEPARATOR . $this->getCharacterImageFolder($characterId);\n    }\n\n    private function getCharacterImageFolder(CharacterId $characterId): string\n    {\n        return 'images' . DIRECTORY_SEPARATOR\n            . 'characters' . DIRECTORY_SEPARATOR\n            . $characterId->toString() . DIRECTORY_SEPARATOR;\n    }\n}\n"
  },
  {
    "path": "app/Modules/Image/UI/Http/CommandMappers/AddImageCommandMapper.php",
    "content": "<?php\n\n\nnamespace App\\Modules\\Image\\UI\\Http\\CommandMappers;\n\nuse App\\Modules\\Character\\Domain\\CharacterId;\nuse App\\Modules\\Image\\Application\\Commands\\AddImageCommand;\nuse Illuminate\\Http\\UploadedFile;\n\nclass AddImageCommandMapper\n{\n    public function map(string $characterId, UploadedFile $uploadedFile): AddImageCommand\n    {\n        return new AddImageCommand(\n            CharacterId::fromString($characterId),\n            $uploadedFile\n        );\n    }\n}\n"
  },
  {
    "path": "app/Modules/Level/Application/Services/LevelService.php",
    "content": "<?php\n\n\nnamespace App\\Modules\\Level\\Application\\Services;\n\nuse App\\Modules\\Level\\Domain\\Level;\n\nclass LevelService\n{\n    public function getLevelByXp(int $xp): Level\n    {\n        $levelId = 1;\n\n        while ($this->getLevelThreshold($levelId) < $xp) {\n            $levelId++;\n        }\n\n        return $this->getLevel($levelId - 1);\n    }\n\n    public function getLevel(int $levelId): Level\n    {\n        return new Level($levelId, $this->getLevelThreshold($levelId), $this->getLevelThreshold($levelId + 1));\n    }\n\n    public function getLevels(int $limit = 100): array\n    {\n        $levelId = 1;\n\n        $levels = [];\n        while ($levelId <= $limit) {\n\n            $levels[] = new Level(\n                $levelId,\n                $this->getLevelThreshold($levelId),\n                $this->getLevelThreshold($levelId + 1)\n            );\n\n            $levelId++;\n        }\n\n        return $levels;\n    }\n\n    private function getLevelThreshold(int $levelId): float\n    {\n        $rawValue = 4 * ($levelId ** 3) / 5;\n\n        return floor($rawValue);\n    }\n}\n"
  },
  {
    "path": "app/Modules/Level/Domain/Level.php",
    "content": "<?php\n\n\nnamespace App\\Modules\\Level\\Domain;\n\n\nclass Level\n{\n    /**\n     * @var int\n     */\n    private $id;\n    /**\n     * @var int\n     */\n    private $currentLevelThreshold;\n    /**\n     * @var int\n     */\n    private $nextLevelThreshold;\n\n    public function __construct(int $id, int $currentLevelThreshHold, int $nextLevelXpThreshold)\n    {\n        $this->id = $id;\n        $this->currentLevelThreshold = $currentLevelThreshHold;\n        $this->nextLevelThreshold = $nextLevelXpThreshold;\n    }\n\n    public function getId(): int\n    {\n        return $this->id;\n    }\n\n    public function getCurrentXpThreshold(): int\n    {\n        return $this->currentLevelThreshold;\n    }\n\n    public function getNextXpThreshold(): int\n    {\n        return $this->nextLevelThreshold;\n    }\n\n    public function getProgress(int $xp):float\n    {\n        $progressRange = $this->nextLevelThreshold - $this->currentLevelThreshold;\n\n        $progressMade = $xp - $this->currentLevelThreshold;\n        $progressMade = $progressMade < 0 ? 0 : $progressMade;\n\n        return ($progressMade / $progressRange) * 100;\n    }\n}\n"
  },
  {
    "path": "app/Modules/Message/Application/Commands/SendMessageCommand.php",
    "content": "<?php\n\n\nnamespace App\\Modules\\Message\\Application\\Commands;\n\n\nuse App\\Modules\\Character\\Domain\\CharacterId;\n\nclass SendMessageCommand\n{\n    /**\n     * @var CharacterId\n     */\n    private $senderId;\n    /**\n     * @var CharacterId\n     */\n    private $recipientId;\n    /**\n     * @var string\n     */\n    private $content;\n\n    public function __construct(CharacterId $senderId, CharacterId $recipientId, string $content)\n    {\n        $this->senderId = $senderId;\n        $this->recipientId = $recipientId;\n        $this->content = $content;\n    }\n\n    public function getSenderId(): CharacterId\n    {\n        return $this->senderId;\n    }\n\n    public function getRecipientId(): CharacterId\n    {\n        return $this->recipientId;\n    }\n\n    public function getContent(): string\n    {\n        return $this->content;\n    }\n}\n"
  },
  {
    "path": "app/Modules/Message/Application/Contracts/MessageRepositoryInterface.php",
    "content": "<?php\n\n\nnamespace App\\Modules\\Message\\Application\\Contracts;\n\nuse App\\Modules\\Message\\Domain\\MessageId;\nuse App\\Modules\\Message\\Domain\\Message;\n\ninterface MessageRepositoryInterface\n{\n    public function nextIdentity(): MessageId;\n\n    public function add(Message $message):void;\n}\n"
  },
  {
    "path": "app/Modules/Message/Application/Services/MessageService.php",
    "content": "<?php\n\n\nnamespace App\\Modules\\Message\\Application\\Services;\n\n\nuse App\\Modules\\Message\\Application\\Contracts\\MessageRepositoryInterface;\nuse App\\Modules\\Message\\Application\\Commands\\SendMessageCommand;\nuse App\\Modules\\Message\\Domain\\Message;\n\nclass MessageService\n{\n    /**\n     * @var MessageRepositoryInterface\n     */\n    private $messageRepository;\n\n    public function __construct(MessageRepositoryInterface $messageRepository)\n    {\n        $this->messageRepository = $messageRepository;\n    }\n\n    public function send(SendMessageCommand $command): void\n    {\n        $message = new Message(\n            $this->messageRepository->nextIdentity(),\n            $command->getSenderId(),\n            $command->getRecipientId(),\n            $command->getContent()\n        );\n\n        $this->messageRepository->add($message);\n    }\n}\n"
  },
  {
    "path": "app/Modules/Message/Domain/Message.php",
    "content": "<?php\n\n\nnamespace App\\Modules\\Message\\Domain;\n\nuse App\\Modules\\Character\\Domain\\CharacterId;\n\nclass Message\n{\n    public const UNREAD = 'unread';\n    public const READ = 'read';\n\n    /**\n     * @var MessageId\n     */\n    private $id;\n    /**\n     * @var CharacterId\n     */\n    private $senderId;\n    /**\n     * @var CharacterId\n     */\n    private $recipientId;\n    /**\n     * @var string\n     */\n    private $content;\n    /**\n     * @var string\n     */\n    private $state;\n\n    public function __construct(\n        MessageId $id,\n        CharacterId $senderId,\n        CharacterId $recipientId,\n        string $content,\n        string $state = self::UNREAD\n    ) {\n        $this->id = $id;\n        $this->senderId = $senderId;\n        $this->recipientId = $recipientId;\n        $this->content = $content;\n        $this->state = $state;\n    }\n\n    public function getId(): MessageId\n    {\n        return $this->id;\n    }\n\n    public function getSenderId(): CharacterId\n    {\n        return $this->senderId;\n    }\n\n    public function getRecipientId(): CharacterId\n    {\n        return $this->recipientId;\n    }\n\n    public function getContent(): string\n    {\n        return $this->content;\n    }\n\n    public function getState(): string\n    {\n        return $this->state;\n    }\n}\n"
  },
  {
    "path": "app/Modules/Message/Domain/MessageId.php",
    "content": "<?php declare(strict_types=1);\n\n\nnamespace App\\Modules\\Message\\Domain;\n\n\nuse App\\Modules\\Generic\\Domain\\BaseId;\n\nclass MessageId extends BaseId\n{\n}\n"
  },
  {
    "path": "app/Modules/Message/Infrastructure/Repositories/MessageRepository.php",
    "content": "<?php\n\nnamespace App\\Modules\\Message\\Infrastructure\\Repositories;\n\nuse App\\Modules\\Message\\Domain\\MessageId;\nuse App\\Modules\\Message\\Domain\\Message;\nuse App\\Models\\Message as MessageModel;\nuse App\\Modules\\Message\\Application\\Contracts\\MessageRepositoryInterface;\nuse App\\Traits\\GeneratesUuid;\nuse Exception;\n\nclass MessageRepository implements MessageRepositoryInterface\n{\n    use GeneratesUuid;\n\n    /**\n     * @return MessageId\n     *\n     * @throws Exception\n     */\n    public function nextIdentity(): MessageId\n    {\n        return MessageId::fromString($this->generateUuid());\n    }\n\n    public function add(Message $message): void\n    {\n        MessageModel::query()->create([\n            'id' => $message->getId()->toString(),\n            'from_id' => $message->getSenderId()->toString(),\n            'to_id' => $message->getRecipientId()->toString(),\n            'content' => $message->getContent(),\n            'state' => $message->getState()\n        ]);\n    }\n}\n"
  },
  {
    "path": "app/Modules/Message/UI/Http/CommandMappers/SendMessageCommandMapper.php",
    "content": "<?php\n\n\nnamespace App\\Modules\\Message\\UI\\Http\\CommandMappers;\n\nuse App\\Models\\Character;\nuse App\\Modules\\Character\\Domain\\CharacterId;\nuse App\\Modules\\Message\\Application\\Commands\\SendMessageCommand;\nuse Illuminate\\Http\\Request;\n\nclass SendMessageCommandMapper\n{\n    public function map(Request $request): SendMessageCommand\n    {\n        /** @var Character $currentCharacter */\n        $user = $request->user();\n        $currentCharacter = $user->character;\n\n        return new SendMessageCommand(\n            CharacterId::fromString($currentCharacter->id),\n            CharacterId::fromString((string)$request->route('character')),\n            (string)$request->get('content')\n        );\n    }\n}\n"
  },
  {
    "path": "app/Modules/Trade/Application/Commands/AddItemToStoreCommand.php",
    "content": "<?php\n\nnamespace App\\Modules\\Trade\\Application\\Commands;\n\nuse App\\Modules\\Character\\Domain\\CharacterId;\nuse App\\Modules\\Equipment\\Domain\\ItemId;\n\nclass AddItemToStoreCommand\n{\n    /**\n     * @var CharacterId\n     */\n    private $characterId;\n    /**\n     * @var int\n     */\n    private $slot;\n    /**\n     * @var ItemId\n     */\n    private $itemId;\n\n    public function __construct(CharacterId $characterId, int $slot, ItemId $itemId)\n    {\n        $this->characterId = $characterId;\n        $this->slot = $slot;\n        $this->itemId = $itemId;\n    }\n\n    public function getCharacterId(): CharacterId\n    {\n        return $this->characterId;\n    }\n\n    public function getSlot(): int\n    {\n        return $this->slot;\n    }\n\n    public function getItemId(): ItemId\n    {\n        return $this->itemId;\n    }\n}\n"
  },
  {
    "path": "app/Modules/Trade/Application/Commands/BuyItemCommand.php",
    "content": "<?php\n\nnamespace App\\Modules\\Trade\\Application\\Commands;\n\nuse App\\Modules\\Character\\Domain\\CharacterId;\nuse App\\Modules\\Equipment\\Domain\\ItemId;\nuse App\\Modules\\Trade\\Domain\\StoreId;\n\nclass BuyItemCommand\n{\n    /**\n     * @var CharacterId\n     */\n    private $customerId;\n    /**\n     * @var StoreId\n     */\n    private $storeId;\n    /**\n     * @var ItemId\n     */\n    private $itemId;\n\n    public function __construct(CharacterId $customerId, StoreId $storeId, ItemId $itemId)\n    {\n        $this->customerId = $customerId;\n        $this->storeId = $storeId;\n        $this->itemId = $itemId;\n    }\n\n    public function getCustomerId(): CharacterId\n    {\n        return $this->customerId;\n    }\n\n    public function getStoreId(): StoreId\n    {\n        return $this->storeId;\n    }\n\n    public function getItemId(): ItemId\n    {\n        return $this->itemId;\n    }\n}\n"
  },
  {
    "path": "app/Modules/Trade/Application/Commands/ChangeItemPriceCommand.php",
    "content": "<?php declare(strict_types=1);\n\nnamespace App\\Modules\\Trade\\Application\\Commands;\n\nuse App\\Modules\\Character\\Domain\\CharacterId;\nuse App\\Modules\\Equipment\\Domain\\ItemId;\nuse App\\Modules\\Equipment\\Domain\\ItemPrice;\nuse App\\Modules\\Generic\\Domain\\ContainerType;\n\nclass ChangeItemPriceCommand\n{\n    /**\n     * @var ItemId\n     */\n    private $itemId;\n    /**\n     * @var ItemPrice\n     */\n    private $itemPrice;\n    /**\n     * @var CharacterId\n     */\n    private $characterId;\n    /**\n     * @var ContainerType\n     */\n    private $containerType;\n\n    public function __construct(\n        ItemId $itemId,\n        ItemPrice $itemPrice,\n        CharacterId $characterId,\n        ContainerType $containerType\n    ) {\n        $this->itemId = $itemId;\n        $this->itemPrice = $itemPrice;\n        $this->characterId = $characterId;\n        $this->containerType = $containerType;\n    }\n\n    public function getItemId(): ItemId\n    {\n        return $this->itemId;\n    }\n\n    public function getItemPrice(): ItemPrice\n    {\n        return $this->itemPrice;\n    }\n\n    public function getCharacterId(): CharacterId\n    {\n        return $this->characterId;\n    }\n\n    public function getContainerType(): ContainerType\n    {\n        return $this->containerType;\n    }\n}\n"
  },
  {
    "path": "app/Modules/Trade/Application/Commands/CreateStoreCommand.php",
    "content": "<?php declare(strict_types=1);\n\n\nnamespace App\\Modules\\Trade\\Application\\Commands;\n\n\nuse App\\Modules\\Character\\Domain\\CharacterId;\n\nclass CreateStoreCommand\n{\n    /**\n     * @var CharacterId\n     */\n    private $characterId;\n\n    public function __construct(CharacterId $characterId)\n    {\n        $this->characterId = $characterId;\n    }\n\n    public function getCharacterId(): CharacterId\n    {\n        return $this->characterId;\n    }\n}\n"
  },
  {
    "path": "app/Modules/Trade/Application/Commands/MoveItemToContainerCommand.php",
    "content": "<?php\n\nnamespace App\\Modules\\Trade\\Application\\Commands;\n\nuse App\\Modules\\Character\\Domain\\CharacterId;\nuse App\\Modules\\Equipment\\Domain\\ItemId;\n\nclass MoveItemToContainerCommand\n{\n    /**\n     * @var ItemId\n     */\n    private $itemId;\n    /**\n     * @var CharacterId\n     */\n    private $characterId;\n\n    public function __construct(ItemId $itemId, CharacterId $characterId)\n    {\n        $this->itemId = $itemId;\n        $this->characterId = $characterId;\n    }\n\n    public function getItemId(): ItemId\n    {\n        return $this->itemId;\n    }\n\n    public function getCharacterId(): CharacterId\n    {\n        return $this->characterId;\n    }\n}\n"
  },
  {
    "path": "app/Modules/Trade/Application/Commands/MoveMoneyToContainerCommand.php",
    "content": "<?php\n\nnamespace App\\Modules\\Trade\\Application\\Commands;\n\nuse App\\Modules\\Character\\Domain\\CharacterId;\nuse App\\Modules\\Equipment\\Domain\\Money;\n\nclass MoveMoneyToContainerCommand\n{\n    /**\n     * @var Money\n     */\n    private $money;\n    /**\n     * @var CharacterId\n     */\n    private $characterId;\n\n    public function __construct(Money $money, CharacterId $characterId)\n    {\n        $this->money = $money;\n        $this->characterId = $characterId;\n    }\n\n    public function getMoney(): Money\n    {\n        return $this->money;\n    }\n\n    public function getCharacterId(): CharacterId\n    {\n        return $this->characterId;\n    }\n}\n"
  },
  {
    "path": "app/Modules/Trade/Application/Commands/SellItemCommand.php",
    "content": "<?php\n\nnamespace App\\Modules\\Trade\\Application\\Commands;\n\nuse App\\Modules\\Character\\Domain\\CharacterId;\nuse App\\Modules\\Equipment\\Domain\\ItemId;\nuse App\\Modules\\Trade\\Domain\\StoreId;\n\nclass SellItemCommand\n{\n    /**\n     * @var CharacterId\n     */\n    private $customerId;\n    /**\n     * @var StoreId\n     */\n    private $storeId;\n    /**\n     * @var ItemId\n     */\n    private $itemId;\n\n    public function __construct(CharacterId $customerId, StoreId $storeId, ItemId $itemId)\n    {\n        $this->customerId = $customerId;\n        $this->storeId = $storeId;\n        $this->itemId = $itemId;\n    }\n\n    public function getCustomerId(): CharacterId\n    {\n        return $this->customerId;\n    }\n\n    public function getStoreId(): StoreId\n    {\n        return $this->storeId;\n    }\n\n    public function getItemId(): ItemId\n    {\n        return $this->itemId;\n    }\n}\n"
  },
  {
    "path": "app/Modules/Trade/Application/Contracts/StoreRepositoryInterface.php",
    "content": "<?php\n\nnamespace App\\Modules\\Trade\\Application\\Contracts;\n\nuse App\\Modules\\Character\\Domain\\CharacterId;\nuse App\\Modules\\Trade\\Domain\\Store;\nuse App\\Modules\\Trade\\Domain\\StoreId;\n\ninterface StoreRepositoryInterface\n{\n    public function nextIdentity(): StoreId;\n\n    public function add(Store $store): void;\n\n    public function getOne(StoreId $storeId): Store;\n\n    public function forCharacter(CharacterId $characterId): Store;\n\n    public function update(Store $store): void;\n}\n"
  },
  {
    "path": "app/Modules/Trade/Application/Services/CreateStoreService.php",
    "content": "<?php declare(strict_types=1);\n\n\nnamespace App\\Modules\\Trade\\Application\\Services;\n\nuse App\\Modules\\Equipment\\Domain\\Money;\nuse App\\Modules\\Trade\\Application\\Commands\\CreateStoreCommand;\nuse App\\Modules\\Trade\\Application\\Contracts\\StoreRepositoryInterface;\nuse App\\Modules\\Trade\\Domain\\Store;\nuse App\\Modules\\Trade\\Domain\\StoreType;\nuse Illuminate\\Support\\Collection;\n\nclass CreateStoreService\n{\n    /**\n     * @var StoreRepositoryInterface\n     */\n    private $storeRepository;\n\n    public function __construct(StoreRepositoryInterface $storeRepository)\n    {\n        $this->storeRepository = $storeRepository;\n    }\n\n    public function create(CreateStoreCommand $command): Store\n    {\n        $id = $this->storeRepository->nextIdentity();\n\n        $store = new Store($id, $command->getCharacterId(), StoreType::sellOnly(), Collection::make(), new Money(0));\n\n        $this->storeRepository->add($store);\n\n        return $store;\n    }\n}\n"
  },
  {
    "path": "app/Modules/Trade/Application/Services/ManageStoreService.php",
    "content": "<?php declare(strict_types=1);\n\n\nnamespace App\\Modules\\Trade\\Application\\Services;\n\nuse App\\Modules\\Equipment\\Application\\Contracts\\InventoryRepositoryInterface;\nuse App\\Modules\\Equipment\\Infrastructure\\Repositories\\ItemRepository;\nuse App\\Modules\\Generic\\Domain\\Container\\ItemNotInContainer;\nuse App\\Modules\\Trade\\Application\\Commands\\ChangeItemPriceCommand;\nuse App\\Modules\\Trade\\Application\\Commands\\MoveItemToContainerCommand;\nuse App\\Modules\\Trade\\Application\\Commands\\MoveMoneyToContainerCommand;\nuse App\\Modules\\Trade\\Application\\Contracts\\StoreRepositoryInterface;\n\nclass ManageStoreService\n{\n    /**\n     * @var StoreRepositoryInterface\n     */\n    private $storeRepository;\n    /**\n     * @var InventoryRepositoryInterface\n     */\n    private $inventoryRepository;\n    /**\n     * @var ItemRepository\n     */\n    private $itemRepository;\n\n    public function __construct(\n        StoreRepositoryInterface $storeRepository,\n        InventoryRepositoryInterface $inventoryRepository,\n        ItemRepository $itemRepository\n    )\n    {\n        $this->storeRepository = $storeRepository;\n        $this->inventoryRepository = $inventoryRepository;\n        $this->itemRepository = $itemRepository;\n    }\n\n    public function moveItemToStore(MoveItemToContainerCommand $command): void\n    {\n        $inventory = $this->inventoryRepository->forCharacter($command->getCharacterId());\n        $store = $this->storeRepository->forCharacter($command->getCharacterId());\n\n        $item = $inventory->takeOut($command->getItemId());\n        $store->add($item);\n\n        $this->inventoryRepository->update($inventory);\n        $this->storeRepository->update($store);\n    }\n\n    public function moveItemToInventory(MoveItemToContainerCommand $command): void\n    {\n        $inventory = $this->inventoryRepository->forCharacter($command->getCharacterId());\n        $store = $this->storeRepository->forCharacter($command->getCharacterId());\n\n        $item = $store->takeOut($command->getItemId());\n        $inventory->add($item);\n\n        $this->inventoryRepository->update($inventory);\n        $this->storeRepository->update($store);\n    }\n\n    public function changeItemPrice(ChangeItemPriceCommand $command): void\n    {\n        $container = $command->getContainerType()->isStore()\n            ? $this->storeRepository->forCharacter($command->getCharacterId())\n            : $this->inventoryRepository->forCharacter($command->getCharacterId());\n\n        $item = $container->findItem($command->getItemId());\n\n        if ($item === null) {\n            throw new ItemNotInContainer('Cannot find item');\n        }\n\n        $item->changePrice($command->getItemPrice());\n\n        $this->itemRepository->update($item);\n    }\n\n    public function moveMoneyToStore(MoveMoneyToContainerCommand $command): void\n    {\n        $inventory = $this->inventoryRepository->forCharacter($command->getCharacterId());\n        $store = $this->storeRepository->forCharacter($command->getCharacterId());\n\n        $money = $inventory->takeMoneyOut($command->getMoney());\n        $store->putMoneyIn($money);\n\n        $this->inventoryRepository->update($inventory);\n        $this->storeRepository->update($store);\n    }\n\n    public function moveMoneyToInventory(MoveMoneyToContainerCommand $command): void\n    {\n        $inventory = $this->inventoryRepository->forCharacter($command->getCharacterId());\n        $store = $this->storeRepository->forCharacter($command->getCharacterId());\n\n        $money = $store->takeMoneyOut($command->getMoney());\n        $inventory->putMoneyIn($money);\n\n        $this->inventoryRepository->update($inventory);\n        $this->storeRepository->update($store);\n    }\n}\n"
  },
  {
    "path": "app/Modules/Trade/Application/Services/TradeService.php",
    "content": "<?php declare(strict_types=1);\n\n\nnamespace App\\Modules\\Trade\\Application\\Services;\n\nuse App\\Modules\\Equipment\\Application\\Contracts\\InventoryRepositoryInterface;\nuse App\\Modules\\Equipment\\Application\\Contracts\\ItemPrototypeRepositoryInterface;\nuse App\\Modules\\Equipment\\Application\\Contracts\\ItemRepositoryInterface;\nuse App\\Modules\\Equipment\\Domain\\ItemPrice;\nuse App\\Modules\\Equipment\\Domain\\Money;\nuse App\\Modules\\Trade\\Application\\Commands\\BuyItemCommand;\nuse App\\Modules\\Trade\\Application\\Commands\\SellItemCommand;\nuse App\\Modules\\Trade\\Application\\Contracts\\StoreRepositoryInterface;\nuse App\\Modules\\Trade\\Domain\\Exception\\SellPriceIsTooHigh;\n\nclass TradeService\n{\n    /**\n     * @var StoreRepositoryInterface\n     */\n    private $storeRepository;\n    /**\n     * @var InventoryRepositoryInterface\n     */\n    private $inventoryRepository;\n    /**\n     * @var ItemPrototypeRepositoryInterface\n     */\n    private $itemPrototypeRepository;\n    /**\n     * @var ItemRepositoryInterface\n     */\n    private $itemRepository;\n\n    public function __construct(\n        StoreRepositoryInterface $storeRepository,\n        InventoryRepositoryInterface $inventoryRepository,\n        ItemPrototypeRepositoryInterface $itemPrototypeRepository,\n        ItemRepositoryInterface $itemRepository\n    )\n    {\n        $this->storeRepository = $storeRepository;\n        $this->inventoryRepository = $inventoryRepository;\n        $this->itemPrototypeRepository = $itemPrototypeRepository;\n        $this->itemRepository = $itemRepository;\n    }\n\n    public function buyItem(BuyItemCommand $command): void\n    {\n        $inventory = $this->inventoryRepository->forCharacter($command->getCustomerId());\n        $store = $this->storeRepository->getOne($command->getStoreId());\n\n        $item = $store->takeOut($command->getItemId());\n        $money = $inventory->takeMoneyOut(new Money($item->getPrice()->getAmount()));\n        $inventory->add($item);\n        $store->putMoneyIn($money);\n\n        $this->inventoryRepository->update($inventory);\n        $this->storeRepository->update($store);\n    }\n\n    public function sellItem(SellItemCommand $command): void\n    {\n        $inventory = $this->inventoryRepository->forCharacter($command->getCustomerId());\n        $store = $this->storeRepository->getOne($command->getStoreId());\n\n        $item = $inventory->takeOut($command->getItemId());\n\n        $itemPrototype = $this->itemPrototypeRepository->getOne($item->getPrototypeId());\n\n        $prototypePrice = $itemPrototype->getPrice()->getAmount();\n        $traderBuyPrice = (int)floor($prototypePrice * 0.75);\n        $customerSellPrice = $item->getPrice()->getAmount();\n\n        if ($traderBuyPrice < $customerSellPrice) {\n            throw new SellPriceIsTooHigh(\n                \"The store is willing to pay no more than {$traderBuyPrice} coins for {$itemPrototype->getName()}\"\n            );\n        }\n\n        $money = $store->takeMoneyOut(new Money($customerSellPrice));\n\n        $item->changePrice(ItemPrice::ofAmount($prototypePrice));\n        $store->add($item);\n        $inventory->putMoneyIn($money);\n\n        $this->itemRepository->update($item);\n        $this->inventoryRepository->update($inventory);\n        $this->storeRepository->update($store);\n    }\n}\n"
  },
  {
    "path": "app/Modules/Trade/Domain/Exception/SellPriceIsTooHigh.php",
    "content": "<?php declare(strict_types=1);\n\n\nnamespace App\\Modules\\Trade\\Domain\\Exception;\n\nuse RuntimeException;\n\nclass SellPriceIsTooHigh extends RuntimeException\n{\n}\n"
  },
  {
    "path": "app/Modules/Trade/Domain/Store/StoreDoesNotBuyItems.php",
    "content": "<?php declare(strict_types=1);\n\n\nnamespace App\\Modules\\Trade\\Domain\\Store;\n\n\nuse RuntimeException;\n\nclass StoreDoesNotBuyItems extends RuntimeException\n{\n}\n"
  },
  {
    "path": "app/Modules/Trade/Domain/Store.php",
    "content": "<?php\n\nnamespace App\\Modules\\Trade\\Domain;\n\nuse App\\Modules\\Character\\Domain\\CharacterId;\nuse App\\Modules\\Equipment\\Domain\\Item;\nuse App\\Modules\\Equipment\\Domain\\ItemId;\nuse App\\Modules\\Equipment\\Domain\\ItemType;\nuse App\\Modules\\Equipment\\Domain\\Money;\nuse App\\Modules\\Generic\\Domain\\Container\\ContainerIsFullException;\nuse App\\Modules\\Generic\\Domain\\Container\\ContainerSlotIsTakenException;\nuse App\\Modules\\Generic\\Domain\\Container\\ContainerSlotOutOfRangeException;\nuse App\\Modules\\Generic\\Domain\\Container\\ItemNotInContainer;\nuse App\\Modules\\Generic\\Domain\\Container\\NotEnoughSpaceInContainerException;\nuse App\\Modules\\Trade\\Domain\\Store\\StoreDoesNotBuyItems;\nuse Illuminate\\Support\\Collection;\n\nclass Store\n{\n    public const NUMBER_OF_SLOTS = 24;\n\n    /**\n     * @var StoreId\n     */\n    private $id;\n\n    /**\n     * @var CharacterId\n     */\n    private $characterId;\n\n    /**\n     * @var Collection\n     */\n    private $items;\n\n    /**\n     * @var StoreType\n     */\n    private $type;\n\n    /**\n     * @var Money\n     */\n    private $money;\n\n    public function __construct(StoreId $id, CharacterId $characterId, StoreType $type, Collection $items, Money $money)\n    {\n        if ($items->count() >= self::NUMBER_OF_SLOTS) {\n            throw new NotEnoughSpaceInContainerException(\n                \"Not enough space in the Store for {$items->count()} new items\"\n            );\n        }\n\n        $this->id = $id;\n        $this->characterId = $characterId;\n        $this->type = $type;\n        $this->items = $items;\n        $this->money = $money;\n    }\n\n    public function getId(): StoreId\n    {\n        return $this->id;\n    }\n\n    public function addItemToSlot(int $slot, Item $item): void\n    {\n        if ($slot >= self::NUMBER_OF_SLOTS) {\n            throw new ContainerSlotOutOfRangeException(\"Store slot $slot is out of range.\");\n        }\n\n        if ($this->items->has($slot)) {\n            throw new ContainerSlotIsTakenException(\"Store slot $slot is already take\");\n        }\n\n        $this->items->put($slot, $item);\n    }\n\n    public function add(Item $item): void\n    {\n        $slot = $this->findFreeSlot();\n\n        $this->items->put($slot, $item);\n    }\n\n    private function findFreeSlot(): int\n    {\n        for ($slot = 0; $slot < self::NUMBER_OF_SLOTS; $slot++) {\n            if (!$this->items->has($slot)) {\n                return $slot;\n            }\n        }\n\n        throw new ContainerIsFullException('Cannot add to full store');\n    }\n\n    public function findItem(ItemId $itemId): ?Item\n    {\n        return $this->items->first(static function (Item $item) use ($itemId) {\n            return $item->getId()->equals($itemId);\n        });\n    }\n\n    public function findItemsOfType(ItemType $type): Collection\n    {\n        return $this->items->filter(static function (Item $item) use ($type) {\n            return $item->isOfType($type);\n        });\n    }\n\n    public function getCharacterId(): CharacterId\n    {\n        return $this->characterId;\n    }\n\n    public function getItems(): Collection\n    {\n        return $this->items;\n    }\n\n    public function takeOut(ItemId $itemId): Item\n    {\n        $slot = $this->items->search(static function (Item $item) use ($itemId) {\n            return $item->getId()->equals($itemId);\n        });\n\n        if ($slot === false) {\n            throw new ItemNotInContainer('Cannot take out item from empty slot');\n        }\n\n        /** @var Item $item */\n        $item = $this->items->get($slot);\n\n        $this->items->forget($slot);\n\n        return $item->toBaseItem();\n    }\n\n    public function putMoneyIn(Money $money): void\n    {\n        $this->money = $this->money->combine($money);\n    }\n\n    public function takeMoneyOut(Money $money): Money\n    {\n        if ($this->type->isSellOnly()) {\n            throw new StoreDoesNotBuyItems('Store does not buy items');\n        }\n\n        $this->money = $this->money->remove($money);\n\n        return $money;\n    }\n\n    public function getMoney(): Money\n    {\n        return $this->money;\n    }\n}\n"
  },
  {
    "path": "app/Modules/Trade/Domain/StoreId.php",
    "content": "<?php declare(strict_types=1);\n\n\nnamespace App\\Modules\\Trade\\Domain;\n\n\nuse App\\Modules\\Generic\\Domain\\BaseId;\n\nclass StoreId extends BaseId\n{\n}\n"
  },
  {
    "path": "app/Modules/Trade/Domain/StoreType.php",
    "content": "<?php\n\nnamespace App\\Modules\\Trade\\Domain;\n\nuse InvalidArgumentException;\n\nclass StoreType\n{\n    public const SELL_ONLY = 'sell_only';\n    public const BUY_AND_SELL = 'buy_and_sell';\n\n    public const TYPES = [\n        self::SELL_ONLY,\n        self::BUY_AND_SELL,\n    ];\n\n    /**\n     * @var string\n     */\n    private $type;\n\n    private function __construct(string $type)\n    {\n        $this->type = $type;\n    }\n\n    public static function ofType(string $type): self\n    {\n        if (!in_array($type, self::TYPES, true)) {\n            throw new InvalidArgumentException(\"$type is not a valid Store Type\");\n        }\n\n        return new self($type);\n    }\n\n    public static function buyAndSell(): self\n    {\n        return new self(self::BUY_AND_SELL);\n    }\n\n    public static function sellOnly(): self\n    {\n        return new self(self::SELL_ONLY);\n    }\n\n    public function toString(): string\n    {\n        return $this->type;\n    }\n\n    public function isSellOnly(): bool\n    {\n        return $this->type === self::SELL_ONLY;\n    }\n}\n"
  },
  {
    "path": "app/Modules/Trade/Infrastructure/ReconstitutionFactories/StoreReconstitutionFactory.php",
    "content": "<?php\n\n\nnamespace App\\Modules\\Trade\\Infrastructure\\ReconstitutionFactories;\n\nuse App\\Models\\Item as ItemModel;\nuse App\\Modules\\Equipment\\Domain\\Money;\nuse App\\Modules\\Equipment\\Infrastructure\\ReconstitutionFactories\\ItemReconstitutionFactory;\nuse App\\Modules\\Trade\\Domain\\Store;\nuse App\\Modules\\Trade\\Domain\\StoreId;\nuse App\\Modules\\Trade\\Domain\\StoreType;\nuse App\\Models\\Store as StoreModel;\nuse App\\Modules\\Character\\Domain\\CharacterId;\n\nclass StoreReconstitutionFactory\n{\n    /**\n     * @var ItemReconstitutionFactory\n     */\n    private $itemReconstitutionFactory;\n\n    public function __construct(ItemReconstitutionFactory $itemReconstitutionFactory)\n    {\n        $this->itemReconstitutionFactory = $itemReconstitutionFactory;\n    }\n\n    public function reconstitute(StoreModel $storeModel): Store\n    {\n        $items = $storeModel->items->mapWithKeys(function (ItemModel $itemModel) {\n\n            $key = $itemModel->getInventorySlotNumber();\n            $inventoryItem = $this->itemReconstitutionFactory->reconstitute($itemModel);\n\n            return [$key => $inventoryItem];\n        });\n\n        return new Store(\n            StoreId::fromString($storeModel->getId()),\n            CharacterId::fromString($storeModel->getCharacterId()),\n            StoreType::ofType($storeModel->getType()),\n            $items,\n            new Money($storeModel->getMoney())\n        );\n    }\n}\n"
  },
  {
    "path": "app/Modules/Trade/Infrastructure/Repositories/StoreRepository.php",
    "content": "<?php\n\nnamespace App\\Modules\\Trade\\Infrastructure\\Repositories;\n\nuse App\\Modules\\Equipment\\Domain\\Item;\nuse App\\Modules\\Trade\\Infrastructure\\ReconstitutionFactories\\StoreReconstitutionFactory;\nuse App\\Models\\Store as StoreModel;\nuse App\\Modules\\Character\\Domain\\CharacterId;\nuse App\\Modules\\Trade\\Application\\Contracts\\StoreRepositoryInterface;\nuse App\\Modules\\Trade\\Domain\\Store;\nuse App\\Modules\\Trade\\Domain\\StoreId;\nuse App\\Traits\\GeneratesUuid;\nuse Exception;\n\nclass StoreRepository implements StoreRepositoryInterface\n{\n    use GeneratesUuid;\n\n    /**\n     * @var StoreReconstitutionFactory\n     */\n    private $reconstitutionFactory;\n\n    public function __construct(StoreReconstitutionFactory $reconstitutionFactory)\n    {\n        $this->reconstitutionFactory = $reconstitutionFactory;\n    }\n\n    /**\n     * @return StoreId\n     *\n     * @throws Exception\n     */\n    public function nextIdentity(): StoreId\n    {\n        return StoreId::fromString($this->generateUuid());\n    }\n\n    public function add(Store $store): void\n    {\n        StoreModel::query()->create([\n            'id' => $store->getId()->toString(),\n            'character_id' => $store->getCharacterId()->toString(),\n            'money' => $store->getMoney()->getValue(),\n        ]);\n    }\n\n    public function getOne(StoreId $storeId): Store\n    {\n        /** @var StoreModel $model */\n        $model = StoreModel::query()->findOrFail($storeId->toString());\n\n        return $this->reconstitutionFactory->reconstitute($model);\n    }\n\n    public function forCharacter(CharacterId $characterId): Store\n    {\n        /** @var StoreModel $model */\n        $model = StoreModel::query()->where('character_id', $characterId->toString())->firstOrFail();\n\n        return $this->reconstitutionFactory->reconstitute($model);\n    }\n\n    public function update(Store $store): void\n    {\n        /** @var StoreModel $storeModel */\n        $storeModel = StoreModel::query()->findOrFail($store->getId()->toString());\n\n        $storeItems = $store->getItems()->mapWithKeys(static function (Item $item, int $slot) {\n\n            $itemId = $item->getId()->toString();\n\n            return [\n                $itemId => [\n                    'item_id' => $itemId,\n                    'price' => $item->getPrice()->getAmount(),\n                    'inventory_slot_number' => $slot,\n                ],\n            ];\n        });\n\n        $storeModel->items()->sync($storeItems->all());\n\n        $storeModel->update([\n            'money' => $store->getMoney()->getValue(),\n        ]);\n    }\n}\n"
  },
  {
    "path": "app/Modules/Trade/UI/Http/CommandMappers/BuyItemCommandMapper.php",
    "content": "<?php\n\nnamespace App\\Modules\\Trade\\UI\\Http\\CommandMappers;\n\nuse App\\Models\\User;\nuse App\\Modules\\Character\\Domain\\CharacterId;\nuse App\\Modules\\Equipment\\Domain\\ItemId;\nuse App\\Modules\\Trade\\Application\\Commands\\BuyItemCommand;\nuse App\\Modules\\Trade\\Domain\\StoreId;\nuse Illuminate\\Http\\Request;\nuse App\\Models\\User as UserModel;\n\nclass BuyItemCommandMapper\n{\n    public function map(Request $request): BuyItemCommand\n    {\n        /** @var UserModel $userModel */\n        $userModel = $request->user();\n\n        return new BuyItemCommand(\n            CharacterId::fromString($userModel->character->getId()),\n            StoreId::fromString((string)$request->route('store')),\n            ItemId::fromString((string)$request->route('item'))\n        );\n    }\n}\n"
  },
  {
    "path": "app/Modules/Trade/UI/Http/CommandMappers/ChangeItemPriceCommandMapper.php",
    "content": "<?php\n\nnamespace App\\Modules\\Trade\\UI\\Http\\CommandMappers;\n\nuse App\\Modules\\Character\\Domain\\CharacterId;\nuse App\\Modules\\Equipment\\Domain\\ItemPrice;\nuse App\\Modules\\Generic\\Domain\\ContainerType;\nuse App\\Modules\\Trade\\Application\\Commands\\ChangeItemPriceCommand;\nuse App\\Modules\\Equipment\\Domain\\ItemId;\nuse Illuminate\\Http\\Request;\nuse App\\Models\\User as UserModel;\n\nclass ChangeItemPriceCommandMapper\n{\n    public function map(Request $request): ChangeItemPriceCommand\n    {\n        /** @var UserModel $userModel */\n        $userModel = $request->user();\n\n        return new ChangeItemPriceCommand(\n            ItemId::fromString((string)$request->route('item')),\n            ItemPrice::ofAmount((int)$request->post('price')),\n            CharacterId::fromString($userModel->character->getId()),\n            ContainerType::fromString((string)$request->post('containerType'))\n        );\n    }\n}\n"
  },
  {
    "path": "app/Modules/Trade/UI/Http/CommandMappers/MoveItemToContainerCommandMapper.php",
    "content": "<?php\n\nnamespace App\\Modules\\Trade\\UI\\Http\\CommandMappers;\n\nuse App\\Modules\\Character\\Domain\\CharacterId;\nuse App\\Modules\\Trade\\Application\\Commands\\MoveItemToContainerCommand;\nuse App\\Modules\\Equipment\\Domain\\ItemId;\nuse Illuminate\\Http\\Request;\nuse App\\Models\\User as UserModel;\n\nclass MoveItemToContainerCommandMapper\n{\n    public function map(Request $request): MoveItemToContainerCommand\n    {\n        /** @var UserModel $userModel */\n        $userModel = $request->user();\n\n        return new MoveItemToContainerCommand(\n            ItemId::fromString((string)$request->route('item')),\n            CharacterId::fromString($userModel->character->getId())\n        );\n    }\n}\n"
  },
  {
    "path": "app/Modules/Trade/UI/Http/CommandMappers/MoveMoneyToContainerCommandMapper.php",
    "content": "<?php\n\nnamespace App\\Modules\\Trade\\UI\\Http\\CommandMappers;\n\nuse App\\Modules\\Character\\Domain\\CharacterId;\nuse App\\Modules\\Equipment\\Domain\\Money;\nuse App\\Modules\\Trade\\Application\\Commands\\MoveMoneyToContainerCommand;\nuse Illuminate\\Http\\Request;\nuse App\\Models\\User as UserModel;\n\nclass MoveMoneyToContainerCommandMapper\n{\n    public function map(Request $request): MoveMoneyToContainerCommand\n    {\n        /** @var UserModel $userModel */\n        $userModel = $request->user();\n\n        return new MoveMoneyToContainerCommand(\n            new Money((int)$request->post('money_amount', 0)),\n            CharacterId::fromString($userModel->character->getId())\n        );\n    }\n}\n"
  },
  {
    "path": "app/Modules/Trade/UI/Http/CommandMappers/SellItemCommandMapper.php",
    "content": "<?php\n\nnamespace App\\Modules\\Trade\\UI\\Http\\CommandMappers;\n\nuse App\\Models\\User;\nuse App\\Modules\\Character\\Domain\\CharacterId;\nuse App\\Modules\\Equipment\\Domain\\ItemId;\nuse App\\Modules\\Trade\\Application\\Commands\\SellItemCommand;\nuse App\\Modules\\Trade\\Domain\\StoreId;\nuse Illuminate\\Http\\Request;\nuse App\\Models\\User as UserModel;\n\nclass SellItemCommandMapper\n{\n    public function map(Request $request): SellItemCommand\n    {\n        /** @var UserModel $userModel */\n        $userModel = $request->user();\n\n        return new SellItemCommand(\n            CharacterId::fromString($userModel->character->getId()),\n            StoreId::fromString((string)$request->route('store')),\n            ItemId::fromString((string)$request->route('item'))\n        );\n    }\n}\n"
  },
  {
    "path": "app/Modules/User/Application/Commands/CreateUserCommand.php",
    "content": "<?php\n\n\nnamespace App\\Modules\\User\\Application\\Commands;\n\n\nclass CreateUserCommand\n{\n    /**\n     * @var string\n     */\n    private $name;\n    /**\n     * @var string\n     */\n    private $email;\n    /**\n     * @var string\n     */\n    private $password;\n\n    public function __construct(string $name, string $email, string $password)\n    {\n        $this->name = $name;\n        $this->email = $email;\n        $this->password = $password;\n    }\n\n    /**\n     * @return string\n     */\n    public function getName(): string\n    {\n        return $this->name;\n    }\n\n    /**\n     * @return string\n     */\n    public function getEmail(): string\n    {\n        return $this->email;\n    }\n\n    /**\n     * @return string\n     */\n    public function getPassword(): string\n    {\n        return $this->password;\n    }\n}\n"
  },
  {
    "path": "app/Modules/User/Application/Services/UserService.php",
    "content": "<?php\n\n\nnamespace App\\Modules\\User\\Application\\Services;\n\nuse App\\Modules\\User\\Application\\Commands\\CreateUserCommand;\nuse App\\Models\\User;\n\nclass UserService\n{\n    public function create(CreateUserCommand $command): User\n    {\n        /** @var User $user */\n        $user =  User::query()->create([\n            'name' => $command->getName(),\n            'email' => $command->getEmail(),\n            'password' => $command->getPassword(),\n        ]);\n\n        return $user;\n    }\n}\n"
  },
  {
    "path": "app/Modules/User/UI/Http/CommandMappers/CreateUserCommandMapper.php",
    "content": "<?php\n\n\nnamespace App\\Modules\\User\\UI\\Http\\CommandMappers;\n\n\nuse App\\Modules\\User\\Application\\Commands\\CreateUserCommand;\n\nclass CreateUserCommandMapper\n{\n    public function map(array $data): CreateUserCommand\n    {\n        return new CreateUserCommand(\n            $data['name'],\n            $data['email'],\n            bcrypt($data['password'])\n        );\n    }\n}\n"
  },
  {
    "path": "app/Providers/AppServiceProvider.php",
    "content": "<?php\n\nnamespace App\\Providers;\n\nuse App\\Modules\\Battle\\Application\\Contracts\\BattleRepositoryInterface;\nuse App\\Modules\\Battle\\Infrastructure\\Repositories\\BattleRepository;\nuse App\\Modules\\Character\\Application\\Contracts\\CharacterRepositoryInterface;\nuse App\\Modules\\Character\\Application\\Contracts\\LocationRepositoryInterface;\nuse App\\Modules\\Character\\Application\\Contracts\\RaceRepositoryInterface;\nuse App\\Modules\\Character\\Infrastructure\\Repositories\\CharacterRepository;\nuse App\\Modules\\Character\\Infrastructure\\Repositories\\LocationRepository;\nuse App\\Modules\\Equipment\\Application\\Contracts\\InventoryRepositoryInterface;\nuse App\\Modules\\Equipment\\Application\\Contracts\\ItemPrototypeRepositoryInterface;\nuse App\\Modules\\Equipment\\Application\\Contracts\\ItemRepositoryInterface;\nuse App\\Modules\\Equipment\\Infrastructure\\Repositories\\InventoryRepository;\nuse App\\Modules\\Equipment\\Infrastructure\\Repositories\\ItemPrototypeRepository;\nuse App\\Modules\\Equipment\\Infrastructure\\Repositories\\ItemRepository;\nuse App\\Modules\\Image\\Application\\Contracts\\ImageRepositoryInterface;\nuse App\\Modules\\Image\\Infrastructure\\Repositories\\ImageRepository;\nuse App\\Modules\\Character\\Infrastructure\\Repositories\\RaceRepository;\nuse App\\Modules\\Message\\Application\\Contracts\\MessageRepositoryInterface;\nuse App\\Modules\\Message\\Infrastructure\\Repositories\\MessageRepository;\nuse App\\Modules\\Trade\\Application\\Contracts\\StoreRepositoryInterface;\nuse App\\Modules\\Trade\\Infrastructure\\Repositories\\StoreRepository;\nuse Illuminate\\Pagination\\Paginator;\nuse Illuminate\\Support\\ServiceProvider;\n\nclass AppServiceProvider extends ServiceProvider\n{\n    /**\n     * Bootstrap any application services.\n     *\n     * @return void\n     */\n    public function boot()\n    {\n        Paginator::useBootstrap();\n    }\n\n    /**\n     * Register any application services.\n     *\n     * @return void\n     */\n    public function register()\n    {\n        $this->registerRepositoryInterfaces();\n    }\n\n    protected function registerRepositoryInterfaces(): self\n    {\n        $this->app->bind(\n            StoreRepositoryInterface::class,\n            StoreRepository::class\n        );\n\n        $this->app->bind(\n            InventoryRepositoryInterface::class,\n            InventoryRepository::class\n        );\n\n        $this->app->bind(\n            LocationRepositoryInterface::class,\n            LocationRepository::class\n        );\n\n        $this->app->bind(\n            RaceRepositoryInterface::class,\n            RaceRepository::class\n        );\n\n        $this->app->bind(\n            CharacterRepositoryInterface::class,\n            CharacterRepository::class\n        );\n\n        $this->app->bind(\n            ItemPrototypeRepositoryInterface::class,\n            ItemPrototypeRepository::class\n        );\n\n        $this->app->bind(\n            ItemRepositoryInterface::class,\n            ItemRepository::class\n        );\n\n        $this->app->bind(\n            BattleRepositoryInterface::class,\n            BattleRepository::class\n        );\n\n        $this->app->bind(\n            MessageRepositoryInterface::class,\n            MessageRepository::class\n        );\n\n        $this->app->bind(\n            ImageRepositoryInterface::class,\n            ImageRepository::class\n        );\n\n\n        return $this;\n    }\n}\n"
  },
  {
    "path": "app/Providers/AuthServiceProvider.php",
    "content": "<?php\n\nnamespace App\\Providers;\n\nuse Illuminate\\Foundation\\Support\\Providers\\AuthServiceProvider as ServiceProvider;\n\nclass AuthServiceProvider extends ServiceProvider\n{\n    /**\n     * The policy mappings for the application.\n     *\n     * @var array\n     */\n    protected $policies = [\n        //'App\\Models\\Model' => 'App\\Policies\\ModelPolicy',\n    ];\n\n    /**\n     * Register any authentication / authorization services.\n     *\n     * @return void\n     */\n    public function boot()\n    {\n        $this->registerPolicies();\n    }\n}\n"
  },
  {
    "path": "app/Providers/BroadcastServiceProvider.php",
    "content": "<?php\n\nnamespace App\\Providers;\n\nuse Illuminate\\Support\\ServiceProvider;\nuse Illuminate\\Support\\Facades\\Broadcast;\n\nclass BroadcastServiceProvider extends ServiceProvider\n{\n    /**\n     * Bootstrap any application services.\n     *\n     * @return void\n     */\n    public function boot()\n    {\n        Broadcast::routes();\n\n        require base_path('routes/channels.php');\n    }\n}\n"
  },
  {
    "path": "app/Providers/EventServiceProvider.php",
    "content": "<?php\n\nnamespace App\\Providers;\n\nuse Illuminate\\Support\\Facades\\Event;\nuse Illuminate\\Foundation\\Support\\Providers\\EventServiceProvider as ServiceProvider;\n\nclass EventServiceProvider extends ServiceProvider\n{\n    /**\n     * The event listener mappings for the application.\n     *\n     * @var array\n     */\n    protected $listen = [\n        'App\\Events\\Event' => [\n            'App\\Listeners\\EventListener',\n        ],\n    ];\n\n    /**\n     * Register any events for your application.\n     *\n     * @return void\n     */\n    public function boot()\n    {\n        //\n    }\n}\n"
  },
  {
    "path": "app/Providers/RouteServiceProvider.php",
    "content": "<?php\n\nnamespace App\\Providers;\n\nuse Illuminate\\Cache\\RateLimiting\\Limit;\nuse Illuminate\\Foundation\\Support\\Providers\\RouteServiceProvider as ServiceProvider;\nuse Illuminate\\Http\\Request;\nuse Illuminate\\Support\\Facades\\RateLimiter;\nuse Illuminate\\Support\\Facades\\Route;\n\nclass RouteServiceProvider extends ServiceProvider\n{\n    /**\n     * The path to the \"home\" route for your application.\n     *\n     * This is used by Laravel authentication to redirect users after login.\n     *\n     * @var string\n     */\n    public const HOME = '/home';\n\n    /**\n     * The controller namespace for the application.\n     *\n     * When present, controller route declarations will automatically be prefixed with this namespace.\n     *\n     * @var string|null\n     */\n     protected $namespace = 'App\\\\Http\\\\Controllers';\n\n    /**\n     * Define your route model bindings, pattern filters, etc.\n     *\n     * @return void\n     */\n    public function boot()\n    {\n        $this->configureRateLimiting();\n\n        $this->routes(function () {\n            Route::prefix('api')\n                ->middleware('api')\n                ->namespace($this->namespace)\n                ->group(base_path('routes/api.php'));\n\n            Route::middleware('web')\n                ->namespace($this->namespace)\n                ->group(base_path('routes/web.php'));\n        });\n    }\n\n    /**\n     * Configure the rate limiters for the application.\n     *\n     * @return void\n     */\n    protected function configureRateLimiting()\n    {\n        RateLimiter::for('api', function (Request $request) {\n            return Limit::perMinute(60)->by(optional($request->user())->id ?: $request->ip());\n        });\n    }\n}"
  },
  {
    "path": "app/Providers/ViewComposerServiceProvider.php",
    "content": "<?php\n\nnamespace App\\Providers;\n\nuse App\\Http\\ViewComposers\\BattlesComposer;\nuse App\\Http\\ViewComposers\\CharacterGeneralInfoComposer;\nuse App\\Http\\ViewComposers\\CharacterMessagesComposer;\nuse App\\Http\\ViewComposers\\MessagesComposer;\nuse Illuminate\\Support\\Facades\\View;\nuse Illuminate\\Support\\ServiceProvider;\n\nclass ViewComposerServiceProvider extends ServiceProvider\n{\n    /**\n     * Register bindings in the container.\n     *\n     * @return void\n     */\n    public function boot()\n    {\n        View::composer('message.index', MessagesComposer::class);\n\n        View::composer('character.message.index', CharacterMessagesComposer::class);\n\n        View::composer('character.partials.general', CharacterGeneralInfoComposer::class);\n\n        View::composer('character.battle.index', BattlesComposer::class);\n    }\n\n    /**\n     * Register the service provider.\n     *\n     * @return void\n     */\n    public function register()\n    {\n        //\n    }\n}\n"
  },
  {
    "path": "app/Support/helpers.php",
    "content": "<?php\n\nif (! function_exists('ini_size_to_kilo_bytes')) {\n\n    function ini_size_to_kilo_bytes(string $value): float\n    {\n        $value = trim($value);\n        $unitSymbol = strtoupper(substr($value, -1));\n\n        $value = (float) $value;\n\n        switch ($unitSymbol) {\n            case 'B':\n                return $value / 1024;\n            case 'M':\n                return $value * 1024;\n            case 'G':\n                return $value * 1048576;\n            default:\n                return $value;\n        }\n    }\n}\n\nif (! function_exists('ini_size_to_bytes')) {\n\n    function ini_size_to_bytes(string $value): float\n    {\n        $value = trim($value);\n        $unitSymbol = strtoupper(substr($value, -1));\n\n        $value = (float) $value;\n\n        switch ($unitSymbol) {\n            case 'K':\n                return $value * 1024;\n            case 'M':\n                return $value * 1048576;\n            case 'G':\n                return $value * 1073741824;\n            default:\n                return $value;\n        }\n    }\n}\n\nif (! function_exists('bytes_to_kilobytes')) {\n\n    function bytes_to_kilobytes(float $bytes): float\n    {\n        return $bytes / 1024;\n    }\n}"
  },
  {
    "path": "app/Traits/GeneratesUuid.php",
    "content": "<?php\n\n\nnamespace App\\Traits;\n\nuse Ramsey\\Uuid\\Uuid;\n\ntrait GeneratesUuid\n{\n    protected function generateUuid(): string\n    {\n        return Uuid::uuid4()->toString();\n    }\n}\n"
  },
  {
    "path": "app/Traits/ThrowsDice.php",
    "content": "<?php\n\n\nnamespace App\\Traits;\n\ntrait ThrowsDice\n{\n    protected static function throwTwoDices(): int\n    {\n        return self::throwOneDice() + self::throwOneDice();\n    }\n\n    protected static function throwTreeDices(): int\n    {\n        return self::throwTwoDices() + self::throwOneDice();\n    }\n\n    protected static function throwOneDice(): int\n    {\n        return rand(1, 6);\n    }\n}"
  },
  {
    "path": "app/Traits/UsesStringId.php",
    "content": "<?php\n\n\nnamespace App\\Traits;\n\ntrait UsesStringId\n{\n    public function getIncrementing()\n    {\n        return false;\n    }\n\n    public function getKeyType()\n    {\n        return 'string';\n    }\n}"
  },
  {
    "path": "artisan",
    "content": "#!/usr/bin/env php\n<?php\n\ndefine('LARAVEL_START', microtime(true));\n\n/*\n|--------------------------------------------------------------------------\n| Register The Auto Loader\n|--------------------------------------------------------------------------\n|\n| Composer provides a convenient, automatically generated class loader\n| for our application. We just need to utilize it! We'll require it\n| into the script here so that we do not have to worry about the\n| loading of any our classes \"manually\". Feels great to relax.\n|\n*/\n\nrequire __DIR__.'/vendor/autoload.php';\n\n$app = require_once __DIR__.'/bootstrap/app.php';\n\n/*\n|--------------------------------------------------------------------------\n| Run The Artisan Application\n|--------------------------------------------------------------------------\n|\n| When we run the console application, the current CLI command will be\n| executed in this console and the response sent back to a terminal\n| or another output device for the developers. Here goes nothing!\n|\n*/\n\n$kernel = $app->make(Illuminate\\Contracts\\Console\\Kernel::class);\n\n$status = $kernel->handle(\n    $input = new Symfony\\Component\\Console\\Input\\ArgvInput,\n    new Symfony\\Component\\Console\\Output\\ConsoleOutput\n);\n\n/*\n|--------------------------------------------------------------------------\n| Shutdown The Application\n|--------------------------------------------------------------------------\n|\n| Once Artisan has finished running, we will fire off the shutdown events\n| so that any final work may be done by the application before we shut\n| down the process. This is the last thing to happen to the request.\n|\n*/\n\n$kernel->terminate($input, $status);\n\nexit($status);\n"
  },
  {
    "path": "bootstrap/app.php",
    "content": "<?php\n\n/*\n|--------------------------------------------------------------------------\n| Create The Application\n|--------------------------------------------------------------------------\n|\n| The first thing we will do is create a new Laravel application instance\n| which serves as the \"glue\" for all the components of Laravel, and is\n| the IoC container for the system binding all of the various parts.\n|\n*/\n\n$app = new Illuminate\\Foundation\\Application(\n    realpath(__DIR__.'/../')\n);\n\n/*\n|--------------------------------------------------------------------------\n| Bind Important Interfaces\n|--------------------------------------------------------------------------\n|\n| Next, we need to bind some important interfaces into the container so\n| we will be able to resolve them when needed. The kernels serve the\n| incoming requests to this application from both the web and CLI.\n|\n*/\n\n$app->singleton(\n    Illuminate\\Contracts\\Http\\Kernel::class,\n    App\\Http\\Kernel::class\n);\n\n$app->singleton(\n    Illuminate\\Contracts\\Console\\Kernel::class,\n    App\\Console\\Kernel::class\n);\n\n$app->singleton(\n    Illuminate\\Contracts\\Debug\\ExceptionHandler::class,\n    App\\Exceptions\\Handler::class\n);\n\n/*\n|--------------------------------------------------------------------------\n| Return The Application\n|--------------------------------------------------------------------------\n|\n| This script returns the application instance. The instance is given to\n| the calling script so we can separate the building of the instances\n| from the actual running of the application and sending responses.\n|\n*/\n\nreturn $app;\n"
  },
  {
    "path": "bootstrap/cache/.gitignore",
    "content": "*\n!.gitignore\n"
  },
  {
    "path": "composer.json",
    "content": "{\n    \"name\": \"mchekin/rpg\",\n    \"type\": \"project\",\n    \"description\": \"Online Role Playing Game.\",\n    \"keywords\": [\n        \"game\",\n        \"rpg-game\",\n        \"browser-game\",\n        \"mmorpg\",\n        \"mmo\",\n        \"roleplaying-game\"\n    ],\n    \"license\": \"MIT\",\n    \"require\": {\n        \"php\": \"^7.3|^8.0\",\n        \"ext-json\": \"*\",\n        \"fideloper/proxy\": \"^4.4\",\n        \"fruitcake/laravel-cors\": \"^2.0\",\n        \"guzzlehttp/guzzle\": \"^7.0.1\",\n        \"intervention/image\": \"^2.4\",\n        \"laravel/framework\": \"^8.12\",\n        \"laravel/legacy-factories\": \"^1.1\",\n        \"laravel/tinker\": \"^2.5\",\n        \"laravel/ui\": \"^3.0\",\n        \"tcg/voyager\": \"^1.4\"\n    },\n    \"require-dev\": {\n        \"barryvdh/laravel-debugbar\": \"^3.2\",\n        \"facade/ignition\": \"^2.5\",\n        \"fakerphp/faker\": \"^1.9.1\",\n        \"laravel/sail\": \"^1.0.1\",\n        \"laravel/dusk\": \"^6.0\",\n        \"mockery/mockery\": \"^1.4.2\",\n        \"nunomaduro/collision\": \"^5.0\",\n        \"phpunit/phpunit\": \"^9.3.3\"\n    },\n    \"autoload\": {\n        \"files\": [\n            \"app/Support/helpers.php\"\n        ],\n        \"psr-4\": {\n            \"App\\\\\": \"app/\",\n            \"Database\\\\Factories\\\\\": \"database/factories/\",\n            \"Database\\\\Seeders\\\\\": \"database/seeders/\"\n        }\n    },\n    \"autoload-dev\": {\n        \"psr-4\": {\n            \"Tests\\\\\": \"tests/\"\n        }\n    },\n    \"scripts\": {\n        \"post-autoload-dump\": [\n            \"Illuminate\\\\Foundation\\\\ComposerScripts::postAutoloadDump\",\n            \"@php artisan package:discover --ansi\"\n        ],\n        \"post-root-package-install\": [\n            \"@php -r \\\"file_exists('.env') || copy('.env.example', '.env');\\\"\"\n        ],\n        \"post-create-project-cmd\": [\n            \"@php artisan key:generate --ansi\"\n        ]\n    },\n    \"repositories\": {\n        \"hooks\": {\n            \"type\": \"composer\",\n            \"url\": \"https://larapack.io\"\n        }\n    },\n    \"extra\": {\n        \"laravel\": {\n            \"dont-discover\": []\n        }\n    },\n    \"config\": {\n        \"optimize-autoloader\": true,\n        \"preferred-install\": \"dist\",\n        \"sort-packages\": true\n    },\n    \"minimum-stability\": \"dev\",\n    \"prefer-stable\": true\n}\n"
  },
  {
    "path": "config/app.php",
    "content": "<?php\n\nreturn [\n\n    /*\n    |--------------------------------------------------------------------------\n    | Application Name\n    |--------------------------------------------------------------------------\n    |\n    | This value is the name of your application. This value is used when the\n    | framework needs to place the application's name in a notification or\n    | any other location as required by the application or its packages.\n    |\n    */\n\n    'name' => env('APP_NAME', 'Laravel'),\n\n    /*\n    |--------------------------------------------------------------------------\n    | Application Environment\n    |--------------------------------------------------------------------------\n    |\n    | This value determines the \"environment\" your application is currently\n    | running in. This may determine how you prefer to configure various\n    | services the application utilizes. Set this in your \".env\" file.\n    |\n    */\n\n    'env' => env('APP_ENV', 'production'),\n\n    /*\n    |--------------------------------------------------------------------------\n    | Application Debug Mode\n    |--------------------------------------------------------------------------\n    |\n    | When your application is in debug mode, detailed error messages with\n    | stack traces will be shown on every error that occurs within your\n    | application. If disabled, a simple generic error page is shown.\n    |\n    */\n\n    'debug' => (bool) env('APP_DEBUG', false),\n\n    /*\n    |--------------------------------------------------------------------------\n    | Application URL\n    |--------------------------------------------------------------------------\n    |\n    | This URL is used by the console to properly generate URLs when using\n    | the Artisan command line tool. You should set this to the root of\n    | your application so that it is used when running Artisan tasks.\n    |\n    */\n\n    'url' => env('APP_URL', 'http://localhost'),\n\n    'asset_url' => env('ASSET_URL', null),\n\n    /*\n    |--------------------------------------------------------------------------\n    | Application Timezone\n    |--------------------------------------------------------------------------\n    |\n    | Here you may specify the default timezone for your application, which\n    | will be used by the PHP date and date-time functions. We have gone\n    | ahead and set this to a sensible default for you out of the box.\n    |\n    */\n\n    'timezone' => 'UTC',\n\n    /*\n    |--------------------------------------------------------------------------\n    | Application Locale Configuration\n    |--------------------------------------------------------------------------\n    |\n    | The application locale determines the default locale that will be used\n    | by the translation service provider. You are free to set this value\n    | to any of the locales which will be supported by the application.\n    |\n    */\n\n    'locale' => 'en',\n\n    /*\n    |--------------------------------------------------------------------------\n    | Application Fallback Locale\n    |--------------------------------------------------------------------------\n    |\n    | The fallback locale determines the locale to use when the current one\n    | is not available. You may change the value to correspond to any of\n    | the language folders that are provided through your application.\n    |\n    */\n\n    'fallback_locale' => 'en',\n\n    /*\n    |--------------------------------------------------------------------------\n    | Faker Locale\n    |--------------------------------------------------------------------------\n    |\n    | This locale will be used by the Faker PHP library when generating fake\n    | data for your database seeds. For example, this will be used to get\n    | localized telephone numbers, street address information and more.\n    |\n    */\n\n    'faker_locale' => 'en_US',\n\n    /*\n    |--------------------------------------------------------------------------\n    | Encryption Key\n    |--------------------------------------------------------------------------\n    |\n    | This key is used by the Illuminate encrypter service and should be set\n    | to a random, 32 character string, otherwise these encrypted strings\n    | will not be safe. Please do this before deploying an application!\n    |\n    */\n\n    'key' => env('APP_KEY'),\n\n    'cipher' => 'AES-256-CBC',\n\n    /*\n    |--------------------------------------------------------------------------\n    | Autoloaded Service Providers\n    |--------------------------------------------------------------------------\n    |\n    | The service providers listed here will be automatically loaded on the\n    | request to your application. Feel free to add your own services to\n    | this array to grant expanded functionality to your applications.\n    |\n    */\n\n    'providers' => [\n\n        /*\n         * Laravel Framework Service Providers...\n         */\n        Illuminate\\Auth\\AuthServiceProvider::class,\n        Illuminate\\Broadcasting\\BroadcastServiceProvider::class,\n        Illuminate\\Bus\\BusServiceProvider::class,\n        Illuminate\\Cache\\CacheServiceProvider::class,\n        Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider::class,\n        Illuminate\\Cookie\\CookieServiceProvider::class,\n        Illuminate\\Database\\DatabaseServiceProvider::class,\n        Illuminate\\Encryption\\EncryptionServiceProvider::class,\n        Illuminate\\Filesystem\\FilesystemServiceProvider::class,\n        Illuminate\\Foundation\\Providers\\FoundationServiceProvider::class,\n        Illuminate\\Hashing\\HashServiceProvider::class,\n        Illuminate\\Mail\\MailServiceProvider::class,\n        Illuminate\\Notifications\\NotificationServiceProvider::class,\n        Illuminate\\Pagination\\PaginationServiceProvider::class,\n        Illuminate\\Pipeline\\PipelineServiceProvider::class,\n        Illuminate\\Queue\\QueueServiceProvider::class,\n        Illuminate\\Redis\\RedisServiceProvider::class,\n        Illuminate\\Auth\\Passwords\\PasswordResetServiceProvider::class,\n        Illuminate\\Session\\SessionServiceProvider::class,\n        Illuminate\\Translation\\TranslationServiceProvider::class,\n        Illuminate\\Validation\\ValidationServiceProvider::class,\n        Illuminate\\View\\ViewServiceProvider::class,\n\n        /*\n         * Package Service Providers...\n         */\n\n        /*\n         * Application Service Providers...\n         */\n        App\\Providers\\AppServiceProvider::class,\n        App\\Providers\\AuthServiceProvider::class,\n        // App\\Providers\\BroadcastServiceProvider::class,\n        App\\Providers\\EventServiceProvider::class,\n        App\\Providers\\RouteServiceProvider::class,\n        \\App\\Providers\\ViewComposerServiceProvider::class,\n\n    ],\n\n    /*\n    |--------------------------------------------------------------------------\n    | Class Aliases\n    |--------------------------------------------------------------------------\n    |\n    | This array of class aliases will be registered when this application\n    | is started. However, feel free to register as many as you wish as\n    | the aliases are \"lazy\" loaded so they don't hinder performance.\n    |\n    */\n\n    'aliases' => [\n\n        'App' => Illuminate\\Support\\Facades\\App::class,\n        'Arr' => Illuminate\\Support\\Arr::class,\n        'Artisan' => Illuminate\\Support\\Facades\\Artisan::class,\n        'Auth' => Illuminate\\Support\\Facades\\Auth::class,\n        'Blade' => Illuminate\\Support\\Facades\\Blade::class,\n        'Broadcast' => Illuminate\\Support\\Facades\\Broadcast::class,\n        'Bus' => Illuminate\\Support\\Facades\\Bus::class,\n        'Cache' => Illuminate\\Support\\Facades\\Cache::class,\n        'Config' => Illuminate\\Support\\Facades\\Config::class,\n        'Cookie' => Illuminate\\Support\\Facades\\Cookie::class,\n        'Crypt' => Illuminate\\Support\\Facades\\Crypt::class,\n        'Date' => Illuminate\\Support\\Facades\\Date::class,\n        'DB' => Illuminate\\Support\\Facades\\DB::class,\n        'Eloquent' => Illuminate\\Database\\Eloquent\\Model::class,\n        'Event' => Illuminate\\Support\\Facades\\Event::class,\n        'File' => Illuminate\\Support\\Facades\\File::class,\n        'Gate' => Illuminate\\Support\\Facades\\Gate::class,\n        'Hash' => Illuminate\\Support\\Facades\\Hash::class,\n        'Http' => Illuminate\\Support\\Facades\\Http::class,\n        'Lang' => Illuminate\\Support\\Facades\\Lang::class,\n        'Log' => Illuminate\\Support\\Facades\\Log::class,\n        'Mail' => Illuminate\\Support\\Facades\\Mail::class,\n        'Notification' => Illuminate\\Support\\Facades\\Notification::class,\n        'Password' => Illuminate\\Support\\Facades\\Password::class,\n        'Queue' => Illuminate\\Support\\Facades\\Queue::class,\n        'Redirect' => Illuminate\\Support\\Facades\\Redirect::class,\n        // 'Redis' => Illuminate\\Support\\Facades\\Redis::class,\n        'Request' => Illuminate\\Support\\Facades\\Request::class,\n        'Response' => Illuminate\\Support\\Facades\\Response::class,\n        'Route' => Illuminate\\Support\\Facades\\Route::class,\n        'Schema' => Illuminate\\Support\\Facades\\Schema::class,\n        'Session' => Illuminate\\Support\\Facades\\Session::class,\n        'Storage' => Illuminate\\Support\\Facades\\Storage::class,\n        'Str' => Illuminate\\Support\\Str::class,\n        'URL' => Illuminate\\Support\\Facades\\URL::class,\n        'Validator' => Illuminate\\Support\\Facades\\Validator::class,\n        'View' => Illuminate\\Support\\Facades\\View::class,\n\n    ],\n\n];"
  },
  {
    "path": "config/auth.php",
    "content": "<?php\n\nreturn [\n\n    /*\n    |--------------------------------------------------------------------------\n    | Authentication Defaults\n    |--------------------------------------------------------------------------\n    |\n    | This option controls the default authentication \"guard\" and password\n    | reset options for your application. You may change these defaults\n    | as required, but they're a perfect start for most applications.\n    |\n    */\n\n    'defaults' => [\n        'guard' => 'web',\n        'passwords' => 'users',\n        'hash' => false,\n    ],\n\n    /*\n    |--------------------------------------------------------------------------\n    | Authentication Guards\n    |--------------------------------------------------------------------------\n    |\n    | Next, you may define every authentication guard for your application.\n    | Of course, a great default configuration has been defined for you\n    | here which uses session storage and the Eloquent user provider.\n    |\n    | All authentication drivers have a user provider. This defines how the\n    | users are actually retrieved out of your database or other storage\n    | mechanisms used by this application to persist your user's data.\n    |\n    | Supported: \"session\", \"token\"\n    |\n    */\n\n    'guards' => [\n        'web' => [\n            'driver' => 'session',\n            'provider' => 'users',\n        ],\n\n        'api' => [\n            'driver' => 'session',\n            'provider' => 'users',\n        ],\n    ],\n\n    /*\n    |--------------------------------------------------------------------------\n    | User Providers\n    |--------------------------------------------------------------------------\n    |\n    | All authentication drivers have a user provider. This defines how the\n    | users are actually retrieved out of your database or other storage\n    | mechanisms used by this application to persist your user's data.\n    |\n    | If you have multiple user tables or models you may configure multiple\n    | sources which represent each model / table. These sources may then\n    | be assigned to any extra authentication guards you have defined.\n    |\n    | Supported: \"database\", \"eloquent\"\n    |\n    */\n\n    'providers' => [\n        'users' => [\n            'driver' => 'eloquent',\n            'model' => \\App\\Models\\User::class,\n        ],\n\n        // 'users' => [\n        //     'driver' => 'database',\n        //     'table' => 'users',\n        // ],\n    ],\n\n    /*\n    |--------------------------------------------------------------------------\n    | Resetting Passwords\n    |--------------------------------------------------------------------------\n    |\n    | You may specify multiple password reset configurations if you have more\n    | than one user table or model in the application and you want to have\n    | separate password reset settings based on the specific user types.\n    |\n    | The expire time is the number of minutes that the reset token should be\n    | considered valid. This security feature keeps tokens short-lived so\n    | they have less time to be guessed. You may change this as needed.\n    |\n    */\n\n    'passwords' => [\n        'users' => [\n            'provider' => 'users',\n            'table' => 'password_resets',\n            'expire' => 60,\n            'throttle' => 60,\n        ],\n    ],\n\n    /*\n    |--------------------------------------------------------------------------\n    | Password Confirmation Timeout\n    |--------------------------------------------------------------------------\n    |\n    | Here you may define the amount of seconds before a password confirmation\n    | times out and the user is prompted to re-enter their password via the\n    | confirmation screen. By default, the timeout lasts for three hours.\n    |\n    */\n\n    'password_timeout' => 10800,\n\n];\n"
  },
  {
    "path": "config/broadcasting.php",
    "content": "<?php\n\nreturn [\n\n    /*\n    |--------------------------------------------------------------------------\n    | Default Broadcaster\n    |--------------------------------------------------------------------------\n    |\n    | This option controls the default broadcaster that will be used by the\n    | framework when an event needs to be broadcast. You may set this to\n    | any of the connections defined in the \"connections\" array below.\n    |\n    | Supported: \"pusher\", \"ably\", \"redis\", \"log\", \"null\"\n    |\n    */\n\n    'default' => env('BROADCAST_DRIVER', 'null'),\n\n    /*\n    |--------------------------------------------------------------------------\n    | Broadcast Connections\n    |--------------------------------------------------------------------------\n    |\n    | Here you may define all of the broadcast connections that will be used\n    | to broadcast events to other systems or over websockets. Samples of\n    | each available type of connection are provided inside this array.\n    |\n    */\n\n    'connections' => [\n\n        'pusher' => [\n            'driver' => 'pusher',\n            'key' => env('PUSHER_APP_KEY'),\n            'secret' => env('PUSHER_APP_SECRET'),\n            'app_id' => env('PUSHER_APP_ID'),\n            'options' => [\n                'cluster' => env('PUSHER_APP_CLUSTER'),\n                'useTLS' => true,\n            ],\n        ],\n\n        'ably' => [\n            'driver' => 'ably',\n            'key' => env('ABLY_KEY'),\n        ],\n\n        'redis' => [\n            'driver' => 'redis',\n            'connection' => 'default',\n        ],\n\n        'log' => [\n            'driver' => 'log',\n        ],\n\n        'null' => [\n            'driver' => 'null',\n        ],\n\n    ],\n\n];\n"
  },
  {
    "path": "config/cache.php",
    "content": "<?php\n\nuse Illuminate\\Support\\Str;\n\nreturn [\n\n    /*\n    |--------------------------------------------------------------------------\n    | Default Cache Store\n    |--------------------------------------------------------------------------\n    |\n    | This option controls the default cache connection that gets used while\n    | using this caching library. This connection is used when another is\n    | not explicitly specified when executing a given caching function.\n    |\n    | Supported: \"apc\", \"array\", \"database\", \"file\",\n    |            \"memcached\", \"redis\", \"dynamodb\"\n    |\n    */\n\n    'default' => env('CACHE_DRIVER', 'file'),\n\n    /*\n    |--------------------------------------------------------------------------\n    | Cache Stores\n    |--------------------------------------------------------------------------\n    |\n    | Here you may define all of the cache \"stores\" for your application as\n    | well as their drivers. You may even define multiple stores for the\n    | same cache driver to group types of items stored in your caches.\n    |\n    | Supported drivers: \"apc\", \"array\", \"database\", \"file\",\n    |            \"memcached\", \"redis\", \"dynamodb\", \"null\"\n    |\n    */\n\n    'stores' => [\n\n        'apc' => [\n            'driver' => 'apc',\n        ],\n\n        'array' => [\n            'driver' => 'array',\n            'serialize' => false,\n        ],\n\n        'database' => [\n            'driver' => 'database',\n            'table' => 'cache',\n            'connection' => null,\n            'lock_connection' => null,\n        ],\n\n        'file' => [\n            'driver' => 'file',\n            'path' => storage_path('framework/cache/data'),\n        ],\n\n        'memcached' => [\n            'driver' => 'memcached',\n            'persistent_id' => env('MEMCACHED_PERSISTENT_ID'),\n            'sasl' => [\n                env('MEMCACHED_USERNAME'),\n                env('MEMCACHED_PASSWORD'),\n            ],\n            'options' => [\n                // Memcached::OPT_CONNECT_TIMEOUT => 2000,\n            ],\n            'servers' => [\n                [\n                    'host' => env('MEMCACHED_HOST', '127.0.0.1'),\n                    'port' => env('MEMCACHED_PORT', 11211),\n                    'weight' => 100,\n                ],\n            ],\n        ],\n\n        'redis' => [\n            'driver' => 'redis',\n            'connection' => 'cache',\n            'lock_connection' => 'default',\n        ],\n\n        'dynamodb' => [\n            'driver' => 'dynamodb',\n            'key' => env('AWS_ACCESS_KEY_ID'),\n            'secret' => env('AWS_SECRET_ACCESS_KEY'),\n            'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),\n            'table' => env('DYNAMODB_CACHE_TABLE', 'cache'),\n            'endpoint' => env('DYNAMODB_ENDPOINT'),\n        ],\n\n    ],\n\n    /*\n    |--------------------------------------------------------------------------\n    | Cache Key Prefix\n    |--------------------------------------------------------------------------\n    |\n    | When utilizing a RAM based store such as APC or Memcached, there might\n    | be other applications utilizing the same cache. So, we'll specify a\n    | value to get prefixed to all our keys so we can avoid collisions.\n    |\n    */\n\n    'prefix' => env('CACHE_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_').'_cache'),\n\n];\n"
  },
  {
    "path": "config/cors.php",
    "content": "<?php\n\nreturn [\n\n    /*\n    |--------------------------------------------------------------------------\n    | Cross-Origin Resource Sharing (CORS) Configuration\n    |--------------------------------------------------------------------------\n    |\n    | Here you may configure your settings for cross-origin resource sharing\n    | or \"CORS\". This determines what cross-origin operations may execute\n    | in web browsers. You are free to adjust these settings as needed.\n    |\n    | To learn more: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS\n    |\n    */\n\n    'paths' => ['api/*', 'sanctum/csrf-cookie'],\n\n    'allowed_methods' => ['*'],\n\n    'allowed_origins' => ['*'],\n\n    'allowed_origins_patterns' => [],\n\n    'allowed_headers' => ['*'],\n\n    'exposed_headers' => [],\n\n    'max_age' => 0,\n\n    'supports_credentials' => false,\n\n];\n"
  },
  {
    "path": "config/database.php",
    "content": "<?php\n\nuse Illuminate\\Support\\Str;\n\nreturn [\n\n    /*\n    |--------------------------------------------------------------------------\n    | Default Database Connection Name\n    |--------------------------------------------------------------------------\n    |\n    | Here you may specify which of the database connections below you wish\n    | to use as your default connection for all database work. Of course\n    | you may use many connections at once using the Database library.\n    |\n    */\n\n    'default' => env('DB_CONNECTION', 'mysql'),\n\n    /*\n    |--------------------------------------------------------------------------\n    | Database Connections\n    |--------------------------------------------------------------------------\n    |\n    | Here are each of the database connections setup for your application.\n    | Of course, examples of configuring each database platform that is\n    | supported by Laravel is shown below to make development simple.\n    |\n    |\n    | All database work in Laravel is done through the PHP PDO facilities\n    | so make sure you have the driver for your particular database of\n    | choice installed on your machine before you begin development.\n    |\n    */\n\n    'connections' => [\n\n        'sqlite' => [\n            'driver' => 'sqlite',\n            'url' => env('DATABASE_URL'),\n            'database' => env('DB_DATABASE', database_path('database.sqlite')),\n            'prefix' => '',\n            'foreign_key_constraints' => env('DB_FOREIGN_KEYS', false),\n        ],\n\n        'mysql' => [\n            'driver' => 'mysql',\n            'url' => env('DATABASE_URL'),\n            'host' => env('DB_HOST', '127.0.0.1'),\n            'port' => env('DB_PORT', '3306'),\n            'database' => env('DB_DATABASE', 'forge'),\n            'username' => env('DB_USERNAME', 'forge'),\n            'password' => env('DB_PASSWORD', ''),\n            'unix_socket' => env('DB_SOCKET', ''),\n            'charset' => 'utf8mb4',\n            'collation' => 'utf8mb4_unicode_ci',\n            'prefix' => '',\n            'strict' => true,\n            'engine' => null,\n            'options' => extension_loaded('pdo_mysql') ? array_filter([\n                PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),\n            ]) : [],\n        ],\n\n        'pgsql' => [\n            'driver' => 'pgsql',\n            'url' => env('DATABASE_URL'),\n            'host' => env('DB_HOST', '127.0.0.1'),\n            'port' => env('DB_PORT', '5432'),\n            'database' => env('DB_DATABASE', 'forge'),\n            'username' => env('DB_USERNAME', 'forge'),\n            'password' => env('DB_PASSWORD', ''),\n            'charset' => 'utf8',\n            'prefix' => '',\n            'schema' => 'public',\n            'sslmode' => 'prefer',\n        ],\n\n        'sqlsrv' => [\n            'driver' => 'sqlsrv',\n            'url' => env('DATABASE_URL'),\n            'host' => env('DB_HOST', 'localhost'),\n            'port' => env('DB_PORT', '1433'),\n            'database' => env('DB_DATABASE', 'forge'),\n            'username' => env('DB_USERNAME', 'forge'),\n            'password' => env('DB_PASSWORD', ''),\n            'charset' => 'utf8',\n            'prefix' => '',\n        ],\n\n    ],\n\n    /*\n    |--------------------------------------------------------------------------\n    | Migration Repository Table\n    |--------------------------------------------------------------------------\n    |\n    | This table keeps track of all the migrations that have already run for\n    | your application. Using this information, we can determine which of\n    | the migrations on disk haven't actually been run in the database.\n    |\n    */\n\n    'migrations' => 'migrations',\n\n    /*\n    |--------------------------------------------------------------------------\n    | Redis Databases\n    |--------------------------------------------------------------------------\n    |\n    | Redis is an open source, fast, and advanced key-value store that also\n    | provides a richer set of commands than a typical key-value systems\n    | such as APC or Memcached. Laravel makes it easy to dig right in.\n    |\n    */\n\n    'redis' => [\n\n        'client' => env('REDIS_CLIENT', 'phpredis'),\n\n        'options' => [\n            'cluster' => env('REDIS_CLUSTER', 'phpredis'),\n            'prefix' => env('REDIS_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_').'_database_'),\n        ],\n\n        'default' => [\n            'url' => env('REDIS_URL'),\n            'host' => env('REDIS_HOST', '127.0.0.1'),\n            'password' => env('REDIS_PASSWORD', null),\n            'port' => env('REDIS_PORT', 6379),\n            'database' => 0,\n        ],\n\n        'cache' => [\n            'url' => env('REDIS_URL'),\n            'host' => env('REDIS_HOST', '127.0.0.1'),\n            'password' => env('REDIS_PASSWORD', null),\n            'port' => env('REDIS_PORT', 6379),\n            'database' => env('REDIS_CACHE_DB', 1),\n        ],\n    ],\n\n];\n"
  },
  {
    "path": "config/filesystems.php",
    "content": "<?php\n\nreturn [\n\n    /*\n    |--------------------------------------------------------------------------\n    | Default Filesystem Disk\n    |--------------------------------------------------------------------------\n    |\n    | Here you may specify the default filesystem disk that should be used\n    | by the framework. The \"local\" disk, as well as a variety of cloud\n    | based disks are available to your application. Just store away!\n    |\n    */\n\n    'default' => env('FILESYSTEM_DRIVER', 'local'),\n\n    /*\n    |--------------------------------------------------------------------------\n    | Filesystem Disks\n    |--------------------------------------------------------------------------\n    |\n    | Here you may configure as many filesystem \"disks\" as you wish, and you\n    | may even configure multiple disks of the same driver. Defaults have\n    | been setup for each driver as an example of the required options.\n    |\n    | Supported Drivers: \"local\", \"ftp\", \"sftp\", \"s3\"\n    |\n    */\n\n    'disks' => [\n\n        'local' => [\n            'driver' => 'local',\n            'root' => storage_path('app'),\n        ],\n\n        'public' => [\n            'driver' => 'local',\n            'root' => storage_path('app/public'),\n            'url' => env('APP_URL').'/storage',\n            'visibility' => 'public',\n        ],\n\n        's3' => [\n            'driver' => 's3',\n            'key' => env('AWS_ACCESS_KEY_ID'),\n            'secret' => env('AWS_SECRET_ACCESS_KEY'),\n            'region' => env('AWS_DEFAULT_REGION'),\n            'bucket' => env('AWS_BUCKET'),\n            'url' => env('AWS_URL'),\n            'endpoint' => env('AWS_ENDPOINT'),\n        ],\n\n    ],\n\n    /*\n    |--------------------------------------------------------------------------\n    | Symbolic Links\n    |--------------------------------------------------------------------------\n    |\n    | Here you may configure the symbolic links that will be created when the\n    | `storage:link` Artisan command is executed. The array keys should be\n    | the locations of the links and the values should be their targets.\n    |\n    */\n\n    'links' => [\n        public_path('storage') => storage_path('app/public'),\n    ],\n\n    'max_size_in_bytes' => min(\n        ini_size_to_bytes(ini_get('post_max_size')),\n        ini_size_to_bytes(ini_get('upload_max_filesize')),\n        ini_size_to_bytes(env('MAX_FILE_SIZE','2M'))\n    ),\n];\n"
  },
  {
    "path": "config/hashing.php",
    "content": "<?php\n\nreturn [\n\n    /*\n    |--------------------------------------------------------------------------\n    | Default Hash Driver\n    |--------------------------------------------------------------------------\n    |\n    | This option controls the default hash driver that will be used to hash\n    | passwords for your application. By default, the bcrypt algorithm is\n    | used; however, you remain free to modify this option if you wish.\n    |\n    | Supported: \"bcrypt\", \"argon\"\n    |\n    */\n\n    'driver' => 'bcrypt',\n\n    /*\n    |--------------------------------------------------------------------------\n    | Bcrypt Options\n    |--------------------------------------------------------------------------\n    |\n    | Here you may specify the configuration options that should be used when\n    | passwords are hashed using the Bcrypt algorithm. This will allow you\n    | to control the amount of time it takes to hash the given password.\n    |\n    */\n\n    'bcrypt' => [\n        'rounds' => env('BCRYPT_ROUNDS', 10),\n    ],\n\n    /*\n    |--------------------------------------------------------------------------\n    | Argon Options\n    |--------------------------------------------------------------------------\n    |\n    | Here you may specify the configuration options that should be used when\n    | passwords are hashed using the Argon algorithm. These will allow you\n    | to control the amount of time it takes to hash the given password.\n    |\n    */\n\n    'argon' => [\n        'memory' => 1024,\n        'threads' => 2,\n        'time' => 2,\n    ],\n\n];"
  },
  {
    "path": "config/hooks.php",
    "content": "<?php\n\nreturn [\n\n    'enabled' => env('HOOKS_ENABLED', true),\n\n];\n"
  },
  {
    "path": "config/image.php",
    "content": "<?php\n\nreturn [\n\n    /*\n    |--------------------------------------------------------------------------\n    | Image Driver\n    |--------------------------------------------------------------------------\n    |\n    | Intervention Image supports \"GD Library\" and \"Imagick\" to process images\n    | internally. You may choose one of them according to your PHP\n    | configuration. By default PHP's \"GD Library\" implementation is used.\n    |\n    | Supported: \"gd\", \"imagick\"\n    |\n    */\n\n    'driver' => 'gd'\n\n];\n"
  },
  {
    "path": "config/logging.php",
    "content": "<?php\n\nuse Monolog\\Handler\\NullHandler;\nuse Monolog\\Handler\\StreamHandler;\nuse Monolog\\Handler\\SyslogUdpHandler;\n\nreturn [\n\n    /*\n    |--------------------------------------------------------------------------\n    | Default Log Channel\n    |--------------------------------------------------------------------------\n    |\n    | This option defines the default log channel that gets used when writing\n    | messages to the logs. The name specified in this option should match\n    | one of the channels defined in the \"channels\" configuration array.\n    |\n    */\n\n    'default' => env('LOG_CHANNEL', 'stack'),\n\n    /*\n    |--------------------------------------------------------------------------\n    | Log Channels\n    |--------------------------------------------------------------------------\n    |\n    | Here you may configure the log channels for your application. Out of\n    | the box, Laravel uses the Monolog PHP logging library. This gives\n    | you a variety of powerful log handlers / formatters to utilize.\n    |\n    | Available Drivers: \"single\", \"daily\", \"slack\", \"syslog\",\n    |                    \"errorlog\", \"monolog\",\n    |                    \"custom\", \"stack\"\n    |\n    */\n\n    'channels' => [\n        'stack' => [\n            'driver' => 'stack',\n            'channels' => ['single'],\n            'ignore_exceptions' => false,\n        ],\n\n        'single' => [\n            'driver' => 'single',\n            'path' => storage_path('logs/laravel.log'),\n            'level' => env('LOG_LEVEL', 'debug'),\n        ],\n\n        'daily' => [\n            'driver' => 'daily',\n            'path' => storage_path('logs/laravel.log'),\n            'level' => env('LOG_LEVEL', 'debug'),\n            'days' => 14,\n        ],\n\n        'slack' => [\n            'driver' => 'slack',\n            'url' => env('LOG_SLACK_WEBHOOK_URL'),\n            'username' => 'Laravel Log',\n            'emoji' => ':boom:',\n            'level' => env('LOG_LEVEL', 'critical'),\n        ],\n\n        'papertrail' => [\n            'driver' => 'monolog',\n            'level' => env('LOG_LEVEL', 'debug'),\n            'handler' => SyslogUdpHandler::class,\n            'handler_with' => [\n                'host' => env('PAPERTRAIL_URL'),\n                'port' => env('PAPERTRAIL_PORT'),\n            ],\n        ],\n\n        'stderr' => [\n            'driver' => 'monolog',\n            'level' => env('LOG_LEVEL', 'debug'),\n            'handler' => StreamHandler::class,\n            'formatter' => env('LOG_STDERR_FORMATTER'),\n            'with' => [\n                'stream' => 'php://stderr',\n            ],\n        ],\n\n        'syslog' => [\n            'driver' => 'syslog',\n            'level' => env('LOG_LEVEL', 'debug'),\n        ],\n\n        'errorlog' => [\n            'driver' => 'errorlog',\n            'level' => env('LOG_LEVEL', 'debug'),\n        ],\n\n        'null' => [\n            'driver' => 'monolog',\n            'handler' => NullHandler::class,\n        ],\n\n        'emergency' => [\n            'path' => storage_path('logs/laravel.log'),\n        ],\n    ],\n\n];\n"
  },
  {
    "path": "config/mail.php",
    "content": "<?php\n\nreturn [\n\n    /*\n    |--------------------------------------------------------------------------\n    | Default Mailer\n    |--------------------------------------------------------------------------\n    |\n    | This option controls the default mailer that is used to send any email\n    | messages sent by your application. Alternative mailers may be setup\n    | and used as needed; however, this mailer will be used by default.\n    |\n    */\n\n    'default' => env('MAIL_MAILER', 'smtp'),\n\n    /*\n    |--------------------------------------------------------------------------\n    | Mailer Configurations\n    |--------------------------------------------------------------------------\n    |\n    | Here you may configure all of the mailers used by your application plus\n    | their respective settings. Several examples have been configured for\n    | you and you are free to add your own as your application requires.\n    |\n    | Laravel supports a variety of mail \"transport\" drivers to be used while\n    | sending an e-mail. You will specify which one you are using for your\n    | mailers below. You are free to add additional mailers as required.\n    |\n    | Supported: \"smtp\", \"sendmail\", \"mailgun\", \"ses\",\n    |            \"postmark\", \"log\", \"array\"\n    |\n    */\n\n    'mailers' => [\n        'smtp' => [\n            'transport' => 'smtp',\n            'host' => env('MAIL_HOST', 'smtp.mailgun.org'),\n            'port' => env('MAIL_PORT', 587),\n            'encryption' => env('MAIL_ENCRYPTION', 'tls'),\n            'username' => env('MAIL_USERNAME'),\n            'password' => env('MAIL_PASSWORD'),\n            'timeout' => null,\n            'auth_mode' => null,\n        ],\n\n        'ses' => [\n            'transport' => 'ses',\n        ],\n\n        'mailgun' => [\n            'transport' => 'mailgun',\n        ],\n\n        'postmark' => [\n            'transport' => 'postmark',\n        ],\n\n        'sendmail' => [\n            'transport' => 'sendmail',\n            'path' => '/usr/sbin/sendmail -bs',\n        ],\n\n        'log' => [\n            'transport' => 'log',\n            'channel' => env('MAIL_LOG_CHANNEL'),\n        ],\n\n        'array' => [\n            'transport' => 'array',\n        ],\n    ],\n\n    /*\n    |--------------------------------------------------------------------------\n    | Global \"From\" Address\n    |--------------------------------------------------------------------------\n    |\n    | You may wish for all e-mails sent by your application to be sent from\n    | the same address. Here, you may specify a name and address that is\n    | used globally for all e-mails that are sent by your application.\n    |\n    */\n\n    'from' => [\n        'address' => env('MAIL_FROM_ADDRESS', 'hello@example.com'),\n        'name' => env('MAIL_FROM_NAME', 'Example'),\n    ],\n\n    /*\n    |--------------------------------------------------------------------------\n    | Markdown Mail Settings\n    |--------------------------------------------------------------------------\n    |\n    | If you are using Markdown based email rendering, you may configure your\n    | theme and component paths here, allowing you to customize the design\n    | of the emails. Or, you may simply stick with the Laravel defaults!\n    |\n    */\n\n    'markdown' => [\n        'theme' => 'default',\n\n        'paths' => [\n            resource_path('views/vendor/mail'),\n        ],\n    ],\n\n];"
  },
  {
    "path": "config/queue.php",
    "content": "<?php\n\nreturn [\n\n    /*\n    |--------------------------------------------------------------------------\n    | Default Queue Connection Name\n    |--------------------------------------------------------------------------\n    |\n    | Laravel's queue API supports an assortment of back-ends via a single\n    | API, giving you convenient access to each back-end using the same\n    | syntax for every one. Here you may define a default connection.\n    |\n    */\n\n    'default' => env('QUEUE_CONNECTION', 'sync'),\n\n    /*\n    |--------------------------------------------------------------------------\n    | Queue Connections\n    |--------------------------------------------------------------------------\n    |\n    | Here you may configure the connection information for each server that\n    | is used by your application. A default configuration has been added\n    | for each back-end shipped with Laravel. You are free to add more.\n    |\n    | Drivers: \"sync\", \"database\", \"beanstalkd\", \"sqs\", \"redis\", \"null\"\n    |\n    */\n\n    'connections' => [\n\n        'sync' => [\n            'driver' => 'sync',\n        ],\n\n        'database' => [\n            'driver' => 'database',\n            'table' => 'jobs',\n            'queue' => 'default',\n            'retry_after' => 90,\n            'after_commit' => false,\n        ],\n\n        'beanstalkd' => [\n            'driver' => 'beanstalkd',\n            'host' => 'localhost',\n            'queue' => 'default',\n            'retry_after' => 90,\n            'block_for' => 0,\n            'after_commit' => false,\n        ],\n\n        'sqs' => [\n            'driver' => 'sqs',\n            'key' => env('AWS_ACCESS_KEY_ID'),\n            'secret' => env('AWS_SECRET_ACCESS_KEY'),\n            'prefix' => env('SQS_PREFIX', 'https://sqs.us-east-1.amazonaws.com/your-account-id'),\n            'queue' => env('SQS_QUEUE', 'default'),\n            'suffix' => env('SQS_SUFFIX'),\n            'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),\n            'after_commit' => false,\n        ],\n\n        'redis' => [\n            'driver' => 'redis',\n            'connection' => 'default',\n            'queue' => env('REDIS_QUEUE', 'default'),\n            'retry_after' => 90,\n            'block_for' => null,\n            'after_commit' => false,\n        ],\n\n    ],\n\n    /*\n    |--------------------------------------------------------------------------\n    | Failed Queue Jobs\n    |--------------------------------------------------------------------------\n    |\n    | These options configure the behavior of failed queue job logging so you\n    | can control which database and table are used to store the jobs that\n    | have failed. You may change them to any database / table you wish.\n    |\n    */\n\n    'failed' => [\n        'driver' => env('QUEUE_FAILED_DRIVER', 'database-uuids'),\n        'database' => env('DB_CONNECTION', 'mysql'),\n        'table' => 'failed_jobs',\n    ],\n\n];\n"
  },
  {
    "path": "config/services.php",
    "content": "<?php\n\nreturn [\n\n    /*\n    |--------------------------------------------------------------------------\n    | Third Party Services\n    |--------------------------------------------------------------------------\n    |\n    | This file is for storing the credentials for third party services such\n    | as Stripe, Mailgun, SparkPost and others. This file provides a sane\n    | default location for this type of information, allowing packages\n    | to have a conventional place to find your various credentials.\n    |\n    */\n\n    'mailgun' => [\n        'domain' => env('MAILGUN_DOMAIN'),\n        'secret' => env('MAILGUN_SECRET'),\n    ],\n\n    'postmark' => [\n        'token' => env('POSTMARK_TOKEN'),\n    ],\n\n    'ses' => [\n        'key' => env('AWS_ACCESS_KEY_ID'),\n        'secret' => env('AWS_SECRET_ACCESS_KEY'),\n        'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),\n    ],\n\n    'sparkpost' => [\n        'secret' => env('SPARKPOST_SECRET'),\n    ],\n\n];\n"
  },
  {
    "path": "config/session.php",
    "content": "<?php\n\nuse Illuminate\\Support\\Str;\n\nreturn [\n\n    /*\n    |--------------------------------------------------------------------------\n    | Default Session Driver\n    |--------------------------------------------------------------------------\n    |\n    | This option controls the default session \"driver\" that will be used on\n    | requests. By default, we will use the lightweight native driver but\n    | you may specify any of the other wonderful drivers provided here.\n    |\n    | Supported: \"file\", \"cookie\", \"database\", \"apc\",\n    |            \"memcached\", \"redis\", \"dynamodb\", \"array\"\n    |\n    */\n\n    'driver' => env('SESSION_DRIVER', 'file'),\n\n    /*\n    |--------------------------------------------------------------------------\n    | Session Lifetime\n    |--------------------------------------------------------------------------\n    |\n    | Here you may specify the number of minutes that you wish the session\n    | to be allowed to remain idle before it expires. If you want them\n    | to immediately expire on the browser closing, set that option.\n    |\n    */\n\n    'lifetime' => env('SESSION_LIFETIME', 120),\n\n    'expire_on_close' => false,\n\n    /*\n    |--------------------------------------------------------------------------\n    | Session Encryption\n    |--------------------------------------------------------------------------\n    |\n    | This option allows you to easily specify that all of your session data\n    | should be encrypted before it is stored. All encryption will be run\n    | automatically by Laravel and you can use the Session like normal.\n    |\n    */\n\n    'encrypt' => false,\n\n    /*\n    |--------------------------------------------------------------------------\n    | Session File Location\n    |--------------------------------------------------------------------------\n    |\n    | When using the native session driver, we need a location where session\n    | files may be stored. A default has been set for you but a different\n    | location may be specified. This is only needed for file sessions.\n    |\n    */\n\n    'files' => storage_path('framework/sessions'),\n\n    /*\n    |--------------------------------------------------------------------------\n    | Session Database Connection\n    |--------------------------------------------------------------------------\n    |\n    | When using the \"database\" or \"redis\" session drivers, you may specify a\n    | connection that should be used to manage these sessions. This should\n    | correspond to a connection in your database configuration options.\n    |\n    */\n\n    'connection' => env('SESSION_CONNECTION', null),\n\n    /*\n    |--------------------------------------------------------------------------\n    | Session Database Table\n    |--------------------------------------------------------------------------\n    |\n    | When using the \"database\" session driver, you may specify the table we\n    | should use to manage the sessions. Of course, a sensible default is\n    | provided for you; however, you are free to change this as needed.\n    |\n    */\n\n    'table' => 'sessions',\n\n    /*\n    |--------------------------------------------------------------------------\n    | Session Cache Store\n    |--------------------------------------------------------------------------\n    |\n    | While using one of the framework's cache driven session backends you may\n    | list a cache store that should be used for these sessions. This value\n    | must match with one of the application's configured cache \"stores\".\n    |\n    | Affects: \"apc\", \"dynamodb\", \"memcached\", \"redis\"\n    |\n    */\n\n    'store' => env('SESSION_STORE', null),\n\n    /*\n    |--------------------------------------------------------------------------\n    | Session Sweeping Lottery\n    |--------------------------------------------------------------------------\n    |\n    | Some session drivers must manually sweep their storage location to get\n    | rid of old sessions from storage. Here are the chances that it will\n    | happen on a given request. By default, the odds are 2 out of 100.\n    |\n    */\n\n    'lottery' => [2, 100],\n\n    /*\n    |--------------------------------------------------------------------------\n    | Session Cookie Name\n    |--------------------------------------------------------------------------\n    |\n    | Here you may change the name of the cookie used to identify a session\n    | instance by ID. The name specified here will get used every time a\n    | new session cookie is created by the framework for every driver.\n    |\n    */\n\n    'cookie' => env(\n        'SESSION_COOKIE',\n        Str::slug(env('APP_NAME', 'laravel'), '_').'_session'\n    ),\n\n    /*\n    |--------------------------------------------------------------------------\n    | Session Cookie Path\n    |--------------------------------------------------------------------------\n    |\n    | The session cookie path determines the path for which the cookie will\n    | be regarded as available. Typically, this will be the root path of\n    | your application but you are free to change this when necessary.\n    |\n    */\n\n    'path' => '/',\n\n    /*\n    |--------------------------------------------------------------------------\n    | Session Cookie Domain\n    |--------------------------------------------------------------------------\n    |\n    | Here you may change the domain of the cookie used to identify a session\n    | in your application. This will determine which domains the cookie is\n    | available to in your application. A sensible default has been set.\n    |\n    */\n\n    'domain' => env('SESSION_DOMAIN', null),\n\n    /*\n    |--------------------------------------------------------------------------\n    | HTTPS Only Cookies\n    |--------------------------------------------------------------------------\n    |\n    | By setting this option to true, session cookies will only be sent back\n    | to the server if the browser has a HTTPS connection. This will keep\n    | the cookie from being sent to you if it can not be done securely.\n    |\n    */\n\n    'secure' => env('SESSION_SECURE_COOKIE'),\n\n    /*\n    |--------------------------------------------------------------------------\n    | HTTP Access Only\n    |--------------------------------------------------------------------------\n    |\n    | Setting this value to true will prevent JavaScript from accessing the\n    | value of the cookie and the cookie will only be accessible through\n    | the HTTP protocol. You are free to modify this option if needed.\n    |\n    */\n\n    'http_only' => true,\n\n    /*\n    |--------------------------------------------------------------------------\n    | Same-Site Cookies\n    |--------------------------------------------------------------------------\n    |\n    | This option determines how your cookies behave when cross-site requests\n    | take place, and can be used to mitigate CSRF attacks. By default, we\n    | will set this value to \"lax\" since this is a secure default value.\n    |\n    | Supported: \"lax\", \"strict\", \"none\", null\n    |\n    */\n\n    'same_site' => 'lax',\n\n];"
  },
  {
    "path": "config/view.php",
    "content": "<?php\n\nreturn [\n\n    /*\n    |--------------------------------------------------------------------------\n    | View Storage Paths\n    |--------------------------------------------------------------------------\n    |\n    | Most templating systems load templates from disk. Here you may specify\n    | an array of paths that should be checked for your views. Of course\n    | the usual Laravel view path has already been registered for you.\n    |\n    */\n\n    'paths' => [\n        resource_path('views'),\n    ],\n\n    /*\n    |--------------------------------------------------------------------------\n    | Compiled View Path\n    |--------------------------------------------------------------------------\n    |\n    | This option determines where all the compiled Blade templates will be\n    | stored for your application. Typically, this is within the storage\n    | directory. However, as usual, you are free to change this value.\n    |\n    */\n\n    'compiled' => realpath(storage_path('framework/views')),\n\n];\n"
  },
  {
    "path": "config/voyager-hooks.php",
    "content": "<?php\n\nreturn [\n\n    'enabled' => env('HOOKS_ENABLED', true),\n\n    'add-route'            => true,\n    'add-hook-menu-item'   => true,\n    'add-hook-permissions' => true,\n    'publish-vendor-files' => true,\n\n];\n"
  },
  {
    "path": "config/voyager.php",
    "content": "<?php\n\nreturn [\n    /*\n    |--------------------------------------------------------------------------\n    | User config\n    |--------------------------------------------------------------------------\n    |\n    | Here you can specify voyager user configs\n    |\n    */\n\n    'user' => [\n        'add_default_role_on_register' => true,\n        'default_role'                 => 'user',\n        // Set `namespace` to `null` to use `config('auth.providers.users.model')` value\n        // Set `namespace` to a class to override auth user model.\n        // However make sure the appointed class must ready to use before installing voyager.\n        // Otherwise `php artisan voyager:install` will fail with class not found error.\n        'namespace'                    => null,\n        'default_avatar'               => 'users/default.png',\n        'redirect'                     => '/admin',\n    ],\n\n    /*\n    |--------------------------------------------------------------------------\n    | Controllers config\n    |--------------------------------------------------------------------------\n    |\n    | Here you can specify voyager controller settings\n    |\n    */\n\n    'controllers' => [\n        'namespace' => 'TCG\\\\Voyager\\\\Http\\\\Controllers',\n    ],\n\n    /*\n    |--------------------------------------------------------------------------\n    | Models config\n    |--------------------------------------------------------------------------\n    |\n    | Here you can specify default model namespace when creating BREAD.\n    | Must include trailing backslashes. If not defined the default application\n    | namespace will be used.\n    |\n    */\n\n    'models' => [\n        //'namespace' => 'App\\\\',\n    ],\n\n    /*\n    |--------------------------------------------------------------------------\n    | Storage Config\n    |--------------------------------------------------------------------------\n    |\n    | Here you can specify attributes related to your application file system\n    |\n    */\n\n    'storage' => [\n        'disk' => env('FILESYSTEM_DRIVER', 'public'),\n    ],\n\n    /*\n    |--------------------------------------------------------------------------\n    | Media Manager\n    |--------------------------------------------------------------------------\n    |\n    | Here you can specify if media manager can show hidden files like(.gitignore)\n    |\n    */\n\n    'hidden_files' => false,\n\n    /*\n    |--------------------------------------------------------------------------\n    | Database Config\n    |--------------------------------------------------------------------------\n    |\n    | Here you can specify voyager database settings\n    |\n    */\n\n    'database' => [\n        'tables' => [\n            'hidden' => ['migrations', 'data_rows', 'data_types', 'menu_items', 'password_resets', 'permission_role', 'settings'],\n        ],\n        'autoload_migrations' => true,\n    ],\n\n    /*\n    |--------------------------------------------------------------------------\n    | Multilingual configuration\n    |--------------------------------------------------------------------------\n    |\n    | Here you can specify if you want Voyager to ship with support for\n    | multilingual and what locales are enabled.\n    |\n    */\n\n    'multilingual' => [\n        /*\n         * Set whether or not the multilingual is supported by the BREAD input.\n         */\n        'enabled' => false,\n\n        /*\n         * Select default language\n         */\n        'default' => 'en',\n\n        /*\n         * Select languages that are supported.\n         */\n        'locales' => [\n            'en',\n            //'pt',\n        ],\n    ],\n\n    /*\n    |--------------------------------------------------------------------------\n    | Dashboard config\n    |--------------------------------------------------------------------------\n    |\n    | Here you can modify some aspects of your dashboard\n    |\n    */\n\n    'dashboard' => [\n        // Add custom list items to navbar's dropdown\n        'navbar_items' => [\n            'voyager::generic.profile' => [\n                'route'      => 'voyager.profile',\n                'classes'    => 'class-full-of-rum',\n                'icon_class' => 'voyager-person',\n            ],\n            'voyager::generic.home' => [\n                'route'        => '/',\n                'icon_class'   => 'voyager-home',\n                'target_blank' => true,\n            ],\n            'voyager::generic.logout' => [\n                'route'      => 'voyager.logout',\n                'icon_class' => 'voyager-power',\n            ],\n        ],\n\n        'widgets' => [\n\n        ],\n\n    ],\n\n    /*\n    |--------------------------------------------------------------------------\n    | Automatic Procedures\n    |--------------------------------------------------------------------------\n    |\n    | When a change happens on Voyager, we can automate some routines.\n    |\n    */\n\n    'bread' => [\n        // When a BREAD is added, create the Menu item using the BREAD properties.\n        'add_menu_item' => true,\n\n        // which menu add item to\n        'default_menu' => 'admin',\n\n        // When a BREAD is added, create the related Permission.\n        'add_permission' => true,\n\n        // which role add premissions to\n        'default_role' => 'admin',\n    ],\n\n    /*\n    |--------------------------------------------------------------------------\n    | UI Generic Config\n    |--------------------------------------------------------------------------\n    |\n    | Here you change some of the Voyager UI settings.\n    |\n    */\n\n    'primary_color' => '#22A7F0',\n\n    'show_dev_tips' => true, // Show development tip \"How To Use:\" in Menu and Settings\n\n    // Here you can specify additional assets you would like to be included in the master.blade\n    'additional_css' => [\n        //'css/custom.css',\n    ],\n\n    'additional_js' => [\n        //'js/custom.js',\n    ],\n\n    'googlemaps' => [\n         'key'    => env('GOOGLE_MAPS_KEY', ''),\n         'center' => [\n             'lat' => env('GOOGLE_MAPS_DEFAULT_CENTER_LAT', '32.715738'),\n             'lng' => env('GOOGLE_MAPS_DEFAULT_CENTER_LNG', '-117.161084'),\n         ],\n         'zoom' => env('GOOGLE_MAPS_DEFAULT_ZOOM', 11),\n     ],\n\n    /*\n    |--------------------------------------------------------------------------\n    | Model specific settings\n    |--------------------------------------------------------------------------\n    |\n    | Here you change some model specific settings\n    |\n    */\n\n    'settings' => [\n        // Enables Laravel cache method for\n        // storing cache values between requests\n        'cache' => false,\n    ],\n\n    // Activate compass when environment is NOT local\n    'compass_in_production' => false,\n\n    'media' => [\n        // The allowed mimetypes to be uploaded through the media-manager.\n        'allowed_mimetypes' => '*', //All types can be uploaded\n        /*\n        'allowed_mimetypes' => [\n          'image/jpeg',\n          'image/png',\n          'image/gif',\n          'image/bmp',\n          'video/mp4',\n        ],\n        */\n       //Path for media-manager. Relative to the filesystem.\n       'path'                => '/',\n       'show_folders'        => true,\n       'allow_upload'        => true,\n       'allow_move'          => true,\n       'allow_delete'        => true,\n       'allow_create_folder' => true,\n       'allow_rename'        => true,\n       /*'watermark'           => [\n            'source'         => 'watermark.png',\n            'position'       => 'bottom-left',\n            'x'              => 0,\n            'y'              => 0,\n            'size'           => 15,\n       ],\n       'thumbnails'          => [\n           [\n                'type'  => 'fit',\n                'name'  => 'fit-500',\n                'width' => 500,\n                'height'=> 500\n           ],\n       ]*/\n   ],\n];\n"
  },
  {
    "path": "database/.gitignore",
    "content": "*.sqlite\n"
  },
  {
    "path": "database/factories/UserFactory.php",
    "content": "<?php\n\nnamespace Database\\Factories;\n\nuse App\\Models\\Character;\nuse App\\Models\\Inventory;\nuse App\\Models\\Item;\nuse App\\Models\\ItemPrototype;\nuse App\\Models\\Location;\nuse App\\Modules\\Character\\Application\\Contracts\\CharacterRepositoryInterface;\nuse App\\Modules\\Character\\Domain\\CharacterType;\nuse App\\Modules\\Character\\Domain\\HitPoints;\nuse App\\Modules\\Character\\Infrastructure\\Repositories\\RaceRepository;\nuse App\\Modules\\Equipment\\Application\\Contracts\\InventoryRepositoryInterface;\nuse App\\Modules\\Equipment\\Application\\Contracts\\ItemRepositoryInterface;\nuse App\\Modules\\Equipment\\Domain\\ItemStatus;\nuse App\\Modules\\Trade\\Application\\Contracts\\StoreRepositoryInterface;\nuse App\\Models\\Race;\nuse App\\Models\\Store;\nuse App\\Models\\User;\nuse App\\Modules\\Trade\\Domain\\StoreType;\nuse Illuminate\\Database\\Eloquent\\Factory;\nuse Illuminate\\Support\\Str;\nuse Faker\\Generator;\n\n/** @var Factory $factory */\n\n$factory->define(User::class, static function (Generator $faker) {\n    static $password;\n\n    return [\n        'name' => $faker->name,\n        'email' => $faker->unique()->safeEmail,\n        'email_verified_at' => now(),\n        'password' => $password ?: $password = bcrypt('secret'),\n        'remember_token' => Str::random(60)\n    ];\n});\n\n$factory->define(Character::class, static function (Generator $faker) {\n\n    /** @var CharacterRepositoryInterface $characterRepository */\n    $characterRepository = resolve(CharacterRepositoryInterface::class);\n\n    /** @var Race $raceModel */\n    $raceModel = Race::query()->inRandomOrder()->first();\n    $location = Location::query()->inRandomOrder()->first();\n\n    $race = (new RaceRepository())->getOne($raceModel->getId());\n    $hitPoints = HitPoints::byRace($race);\n\n    $genders = ['male', 'female'];\n    $types = CharacterType::TYPES;\n\n    $characterId = $characterRepository->nextIdentity()->toString();\n\n    return [\n        'id' => $characterId,\n\n        'race_id' => $race->getId(),\n\n        'level_id' => 1,\n\n        'location_id' => $location,\n\n        'name' => $faker->name,\n        'gender' => $genders[array_rand($genders)],\n        'type' => $characterType = $types[array_rand($types)],\n\n        'xp' => 0,\n        'reputation' => 0,\n\n        // attributes\n        'strength' => $race->getStrength(),\n        'agility' => $race->getAgility(),\n        'constitution' => $race->getConstitution(),\n        'intelligence' => $race->getIntelligence(),\n        'charisma' => $race->getCharisma(),\n\n        'hit_points' => $hitPoints->getCurrentHitPoints(),\n        'total_hit_points' => $hitPoints->getMaximumHitPoints(),\n\n        'user_id' => static function () use ($characterType) {\n            return $characterType === CharacterType::PLAYER\n                ? factory(User::class)->create()->id\n                : null;\n        },\n    ];\n});\n\n$factory->afterCreating(Character::class, static function (Character $character) {\n\n    /** @var InventoryRepositoryInterface $inventoryRepository */\n    $inventoryRepository = resolve(InventoryRepositoryInterface::class);\n\n    /** @var StoreRepositoryInterface $storeRepository */\n    $storeRepository = resolve(StoreRepositoryInterface::class);\n\n    Inventory::query()->create([\n        'id' => $inventoryRepository->nextIdentity()->toString(),\n        'character_id' => $character->getId(),\n        'money' => random_int(0, 5000),\n    ]);\n\n    Store::query()->create([\n        'id' => $storeRepository->nextIdentity()->toString(),\n        'character_id' => $character->getId(),\n        'money' => random_int(0, 5000),\n        'type' => $character->isMerchant() ? StoreType::BUY_AND_SELL : StoreType::SELL_ONLY,\n    ]);\n});\n\n\n$factory->define(Item::class, static function () {\n    static $charactersIds = [];\n\n    /** @var ItemRepositoryInterface $itemRepository */\n    $itemRepository = resolve(ItemRepositoryInterface::class);\n\n    /** @var ItemPrototype $itemPrototype */\n    $itemPrototype = ItemPrototype::query()->inRandomOrder()->first();\n\n    /** @var Character $character */\n    $character = Character::query()->whereNotIn('id', $charactersIds)->first();\n\n    $charactersIds[] = $character->getId();\n\n    $itemId = $itemRepository->nextIdentity()->toString();\n\n    return [\n        'id' => $itemId,\n        'name' => $itemPrototype->getName(),\n        'description' => $itemPrototype->getDescription(),\n        'effects' => $itemPrototype->getEffects(),\n        'price' => $itemPrototype->getPrice(),\n        'type' => $itemPrototype->getType(),\n        'image_file_path' => $itemPrototype->getImageFilePath(),\n        'prototype_id' => $itemPrototype->getId(),\n        'creator_character_id' => $character->getId(),\n    ];\n});\n\n$factory->afterCreating(Item::class, static function (Item $item) {\n\n    static $charactersIds = [];\n\n    /** @var Character $character */\n    $character = Character::query()->whereNotIn('id', $charactersIds)->first();\n\n    $charactersIds[] = $character->getId();\n\n    $character->inventory->items()->attach($item->getId(), [\n        'inventory_slot_number' => 0,\n        'status' => ItemStatus::EQUIPPED,\n    ]);\n});\n\n$factory->afterCreating(Item::class, static function (Item $item) {\n\n    static $charactersIds = [];\n\n    /** @var Character $character */\n    $character = Character::query()->whereNotIn('id', $charactersIds)->first();\n\n    $charactersIds[] = $character->getId();\n\n    $character->store->items()->attach($item->getId(), [\n        'inventory_slot_number' => 0,\n    ]);\n});\n"
  },
  {
    "path": "database/migrations/2014_10_12_000000_create_users_table.php",
    "content": "<?php\n\nuse Illuminate\\Database\\Migrations\\Migration;\nuse Illuminate\\Database\\Schema\\Blueprint;\nuse Illuminate\\Support\\Facades\\Schema;\n\nclass CreateUsersTable extends Migration\n{\n    /**\n     * Run the migrations.\n     *\n     * @return void\n     */\n    public function up()\n    {\n        Schema::create('users', function (Blueprint $table) {\n            $table->id();\n            $table->string('name');\n            $table->string('email')->unique();\n            $table->timestamp('email_verified_at')->nullable();\n            $table->string('password');\n            $table->rememberToken();\n            $table->timestamps();\n        });\n    }\n\n    /**\n     * Reverse the migrations.\n     *\n     * @return void\n     */\n    public function down()\n    {\n        Schema::dropIfExists('users');\n    }\n}\n"
  },
  {
    "path": "database/migrations/2014_10_12_100000_create_password_resets_table.php",
    "content": "<?php\n\nuse Illuminate\\Support\\Facades\\Schema;\nuse Illuminate\\Database\\Schema\\Blueprint;\nuse Illuminate\\Database\\Migrations\\Migration;\n\nclass CreatePasswordResetsTable extends Migration\n{\n    /**\n     * Run the migrations.\n     *\n     * @return void\n     */\n    public function up()\n    {\n        Schema::create('password_resets', function (Blueprint $table) {\n            $table->string('email')->index();\n            $table->string('token');\n            $table->timestamp('created_at')->nullable();\n        });\n    }\n\n    /**\n     * Reverse the migrations.\n     *\n     * @return void\n     */\n    public function down()\n    {\n        Schema::dropIfExists('password_resets');\n    }\n}\n"
  },
  {
    "path": "database/migrations/2017_05_14_055744_create_locations_table.php",
    "content": "<?php\n\nuse App\\Models\\Location;\nuse App\\Modules\\Character\\Application\\Contracts\\LocationRepositoryInterface;\nuse Illuminate\\Support\\Facades\\Schema;\nuse Illuminate\\Database\\Schema\\Blueprint;\nuse Illuminate\\Database\\Migrations\\Migration;\n\nclass CreateLocationsTable extends Migration\n{\n    /**\n     * Run the migrations.\n     *\n     * @return void\n     */\n    public function up()\n    {\n        Schema::create('locations', static function (Blueprint $table) {\n            $table->bigIncrements('auto_id');\n            $table->uuid('id')->index();\n\n            $table->string('name')->unique();\n            $table->string('description');\n\n            $table->string('image');\n            $table->string('image_sm');\n\n            $table->timestamps();\n        });\n\n        Schema::create('adjacent_location', static function (Blueprint $table) {\n\n            $table->uuid('location_id')->index();\n            $table->uuid('adjacent_location_id')->index();\n\n            $table->primary(['location_id', 'adjacent_location_id']);\n\n            $table->enum('direction', Location::getDirections());\n\n            $table->foreign('location_id')->references('id')->on('locations')->onDelete('cascade');\n            $table->foreign('adjacent_location_id')->references('id')->on('locations')->onDelete('cascade');\n\n            $table->timestamps();\n        });\n\n\n        /** @var LocationRepositoryInterface $locationRepository */\n        $locationRepository = resolve(LocationRepositoryInterface::class);\n\n        $locations = [\n            [\n                'id' => $locationRepository->nextIdentity()->toString(),\n                'name' => 'Inn',\n                'description' => 'An establishment or building providing lodging and, usually, food and drink for travelers (Starting location)',\n                'image' => 'locations/Inn-800px.png',\n                'image_sm' => 'locations/Inn-300px.png',\n            ],\n            array(\n                'id' => $locationRepository->nextIdentity()->toString(),\n                'name' => 'Town Hall',\n                'description' => 'Public forum or meeting in which those attending gather to discuss civic or political issues, hear and ask questions about the ideas of a candidate for public office',\n                'image' => 'locations/Townhall-800px.png',\n                'image_sm' => 'locations/Townhall-300px.png',\n            ),\n            [\n                'id' => $locationRepository->nextIdentity()->toString(),\n                'name' => 'Smithy',\n                'description' => \"A blacksmith's shop. A place to purchase weaponry and armor or train one's skill as a blacksmith\",\n                'image' => 'locations/Blacksmith-800px.png',\n                'image_sm' => 'locations/Blacksmith-300px.png',\n            ],\n            [\n                'id' => $locationRepository->nextIdentity()->toString(),\n                'name' => 'Military academy fortress',\n                'description' => 'An institute where soldiers and mercenaries train they martial skills',\n                'image' => 'locations/Fortress-800px.png',\n                'image_sm' => 'locations/Fortress-300px.png',\n            ],\n        ];\n\n        foreach ($locations as $location) {\n            Location::query()->forceCreate($location);\n        }\n\n        $adjacent_locations = [\n            [\n                'location_id' => $locations[0]['id'],\n                'adjacent_location_id' => $locations[1]['id'],\n                'direction' => 'north',\n            ],\n            [\n                'location_id' => $locations[0]['id'],\n                'adjacent_location_id' => $locations[2]['id'],\n                'direction' => 'east',\n            ],\n            [\n                'location_id' => $locations[0]['id'],\n                'adjacent_location_id' => $locations[3]['id'],\n                'direction' => 'south',\n            ],\n        ];\n\n        foreach ($adjacent_locations as $record) {\n            /** @var  $location Location */\n            $location = Location::query()->find($record['location_id']);\n\n            /** @var  $adjacent_location Location */\n            $adjacent_location = Location::query()->find($record['adjacent_location_id']);\n\n            $location->addAdjacentLocation($adjacent_location, $record['direction']);\n        }\n    }\n\n    /**\n     * Reverse the migrations.\n     *\n     * @return void\n     */\n    public function down()\n    {\n        Schema::dropIfExists('adjacent_location');\n        Schema::dropIfExists('locations');\n    }\n}\n"
  },
  {
    "path": "database/migrations/2017_05_14_055823_create_races_table.php",
    "content": "<?php\n\nuse App\\Models\\Location;\nuse App\\Models\\Race;\nuse Illuminate\\Support\\Facades\\Schema;\nuse Illuminate\\Database\\Schema\\Blueprint;\nuse Illuminate\\Database\\Migrations\\Migration;\n\nclass CreateRacesTable extends Migration\n{\n    /**\n     * Run the migrations.\n     *\n     * @return void\n     */\n    public function up()\n    {\n        Schema::create('races', function (Blueprint $table) {\n            $table->integer('id')->unsigned()->primary();\n\n            $table->string(\"name\");\n            $table->string(\"description\");\n\n            $table->string(\"male_image\");\n            $table->string(\"female_image\");\n\n            // attributes\n            $table->integer('strength');\n            $table->integer('agility');\n            $table->integer('constitution');\n            $table->integer('intelligence');\n            $table->integer('charisma');\n\n            // locations\n            $table->uuid('starting_location_id');\n            $table->foreign('starting_location_id')\n                ->references('id')\n                ->on('locations')\n                ->onDelete('restrict');\n\n            $table->timestamps();\n        });\n\n        /** @var Location $location */\n        $location = Location::query()->firstOrFail();\n\n        $races = [\n            [\n                \"id\" => 1,\n                \"name\" => \"Human\",\n                \"description\" => \"This race combines in itself all the properties of the other races, albeit they are less pronounced.\",\n\n                \"male_image\" => \"images/races/human-male.png\",\n                \"female_image\" => \"images/races/human-female.png\",\n\n                \"strength\" => 5,\n                \"agility\" => 5,\n                \"constitution\" => 5,\n                \"intelligence\" => 5,\n                \"charisma\" => 1,\n\n                \"starting_location_id\" => $location->getId(),\n            ],\n            [\n                \"id\" => 2,\n                \"name\" => \"Elf\",\n                \"description\" => \"This race is known for it's great agility, but lacks constitution.\",\n\n                \"male_image\" => \"images/races/elf-male.png\",\n                \"female_image\" => \"images/races/elf-female.png\",\n\n                \"strength\" => 5,\n                \"agility\" => 9,\n                \"constitution\" => 1,\n                \"intelligence\" => 5,\n                \"charisma\" => 1,\n\n                \"starting_location_id\" => $location->getId(),\n            ],\n            [\n                \"id\" => 3,\n                \"name\" => \"Dwarf\",\n                \"description\" => \"This race is known for it's constitution and resilience, but lack agility and grace.\",\n\n                \"male_image\" => \"images/races/dwarf-male.png\",\n                \"female_image\" => \"images/races/dwarf-female.png\",\n\n                \"strength\" => 5,\n                \"agility\" => 1,\n                \"constitution\" => 9,\n                \"intelligence\" => 5,\n                \"charisma\" => 1,\n\n                \"starting_location_id\" => $location->getId(),\n            ],\n            [\n                \"id\" => 4,\n                \"name\" => \"Orc\",\n                \"description\" => \"This race enjoys great physical strength, but lacks intelligence.\",\n\n                \"male_image\" => \"images/races/orc-male.png\",\n                \"female_image\" => \"images/races/orc-female.png\",\n\n                \"strength\" => 9,\n                \"agility\" => 5,\n                \"constitution\" => 5,\n                \"intelligence\" => 1,\n                \"charisma\" => 1,\n\n                \"starting_location_id\" => $location->getId(),\n            ],\n        ];\n\n        foreach ($races as $race)\n        {\n            Race::query()->forceCreate($race);\n        }\n    }\n\n    /**\n     * Reverse the migrations.\n     *\n     * @return void\n     */\n    public function down()\n    {\n        Schema::dropIfExists('races');\n    }\n}\n"
  },
  {
    "path": "database/migrations/2017_05_14_055844_create_characters_table.php",
    "content": "<?php\n\nuse Illuminate\\Support\\Facades\\Schema;\nuse Illuminate\\Database\\Schema\\Blueprint;\nuse Illuminate\\Database\\Migrations\\Migration;\n\nclass CreateCharactersTable extends Migration\n{\n    /**\n     * Run the migrations.\n     *\n     * @return void\n     */\n    public function up()\n    {\n        Schema::create('characters', function (Blueprint $table) {\n            $table->bigIncrements('auto_id');\n            $table->uuid('id')->index();\n\n            $table->string('name')->unique();\n            $table->enum('gender', ['male', 'female']);\n            $table->enum('type', ['player', 'merchant', 'civilian', 'monster']);\n\n            $table->unsignedInteger('xp')->default(0);\n            $table->unsignedInteger('available_attribute_points')->default(0);\n            $table->integer('reputation');\n\n            // attributes\n            $table->integer('strength');\n            $table->integer('agility');\n            $table->integer('constitution');\n            $table->integer('intelligence');\n            $table->integer('charisma');\n\n            // stats\n            $table->integer('hit_points');\n            $table->integer('total_hit_points');\n\n            // statistics\n            $table->integer('battles_won')->default(0);\n            $table->integer('battles_lost')->default(0);\n\n            $table->unsignedInteger('level_id');\n\n            $table->unsignedBigInteger('user_id')->nullable();\n            $table->foreign('user_id')->references('id')->on('users')->onDelete('set null');\n\n            $table->uuid('location_id');\n            $table->foreign('location_id')->references('id')->on('locations')->onDelete('restrict');\n\n            $table->unsignedInteger('race_id');\n            $table->foreign('race_id')->references('id')->on('races')->onDelete('restrict');\n\n            $table->uuid('profile_picture_id')->nullable();\n\n            $table->timestamps();\n        });\n    }\n\n    /**\n     * Reverse the migrations.\n     *\n     * @return void\n     */\n    public function down()\n    {\n        Schema::dropIfExists('characters');\n    }\n}\n"
  },
  {
    "path": "database/migrations/2017_05_16_144929_create_battles_table.php",
    "content": "<?php\n\nuse Illuminate\\Support\\Facades\\Schema;\nuse Illuminate\\Database\\Schema\\Blueprint;\nuse Illuminate\\Database\\Migrations\\Migration;\n\nclass CreateBattlesTable extends Migration\n{\n    /**\n     * Run the migrations.\n     *\n     * @return void\n     */\n    public function up()\n    {\n        Schema::create('battles', function (Blueprint $table) {\n            $table->bigIncrements('auto_id');\n            $table->uuid('id')->index();\n\n            $table->boolean('seen_by_defender')->default(0);\n\n            $table->uuid('location_id');\n            $table->foreign('location_id')->references('id')->on('locations')->onDelete('restrict');\n\n            $table->uuid('attacker_id');\n            $table->foreign('attacker_id')->references('id')->on('characters')->onDelete('restrict');\n\n            $table->uuid('defender_id');\n            $table->foreign('defender_id')->references('id')->on('characters')->onDelete('restrict');\n\n            $table->uuid('victor_id')->nullable();\n            $table->foreign('victor_id')->references('id')->on('characters')->onDelete('restrict');\n\n            $table->unsignedInteger('victor_xp_gained')->default(0);\n\n            $table->timestamps();\n        });\n    }\n\n    /**\n     * Reverse the migrations.\n     *\n     * @return void\n     */\n    public function down()\n    {\n        Schema::dropIfExists('battles');\n    }\n}\n"
  },
  {
    "path": "database/migrations/2017_05_16_181330_create_battle_rounds_table.php",
    "content": "<?php\n\nuse Illuminate\\Support\\Facades\\Schema;\nuse Illuminate\\Database\\Schema\\Blueprint;\nuse Illuminate\\Database\\Migrations\\Migration;\n\nclass CreateBattleRoundsTable extends Migration\n{\n    /**\n     * Run the migrations.\n     *\n     * @return void\n     */\n    public function up()\n    {\n        Schema::create('battle_rounds', function (Blueprint $table) {\n            $table->bigIncrements('auto_id');\n            $table->uuid('id')->index();\n\n            $table->uuid('battle_id');\n            $table->foreign('battle_id')->references('id')->on('battles')->onDelete('restrict');\n\n            $table->timestamps();\n        });\n    }\n\n    /**\n     * Reverse the migrations.\n     *\n     * @return void\n     */\n    public function down()\n    {\n        Schema::dropIfExists('battle_rounds');\n    }\n}\n"
  },
  {
    "path": "database/migrations/2017_05_16_181844_create_battle_turns_table.php",
    "content": "<?php\n\nuse App\\Modules\\Battle\\Domain\\BattleTurnResult;\nuse Illuminate\\Support\\Facades\\Schema;\nuse Illuminate\\Database\\Schema\\Blueprint;\nuse Illuminate\\Database\\Migrations\\Migration;\n\nclass CreateBattleTurnsTable extends Migration\n{\n    /**\n     * Run the migrations.\n     *\n     * @return void\n     */\n    public function up()\n    {\n        Schema::create('battle_turns', function (Blueprint $table) {\n            $table->bigIncrements('auto_id');\n            $table->uuid('id')->index();\n\n            $table->integer('damageDone')->default(0);\n\n            $table->integer('damageAbsorbed')->default(0);\n\n            $table->enum('result_type', BattleTurnResult::TYPES);\n\n            $table->uuid('executor_id');\n            $table->foreign('executor_id')->references('id')->on('characters')->onDelete('restrict');\n\n            $table->uuid('target_id');\n            $table->foreign('target_id')->references('id')->on('characters')->onDelete('restrict');\n\n            $table->uuid('battle_round_id');\n            $table->foreign('battle_round_id')->references('id')->on('battle_rounds')->onDelete('restrict');\n\n            $table->timestamps();\n        });\n    }\n\n    /**\n     * Reverse the migrations.\n     *\n     * @return void\n     */\n    public function down()\n    {\n        Schema::dropIfExists('battle_turns');\n    }\n}\n"
  },
  {
    "path": "database/migrations/2017_11_26_013050_add_user_role_relationship.php",
    "content": "<?php\n\nuse Illuminate\\Database\\Migrations\\Migration;\nuse Illuminate\\Database\\Schema\\Blueprint;\nuse Illuminate\\Support\\Facades\\Schema;\nuse Illuminate\\Support\\Facades\\DB;\n\nclass AddUserRoleRelationship extends Migration\n{\n    /**\n     * Run the migrations.\n     *\n     * @return void\n     */\n    public function up()\n    {\n        Schema::table('users', function (Blueprint $table) {\n            $table->bigInteger('role_id')->unsigned()->change();\n            $table->foreign('role_id')->references('id')->on('roles');\n        });\n    }\n\n    /**\n     * Reverse the migrations.\n     *\n     * @return void\n     */\n    public function down()\n    {\n        Schema::table('users', function (Blueprint $table) {\n            if (DB::getDriverName() !== 'sqlite') {\n                $table->dropForeign(['role_id']);\n            }\n        });\n\n        Schema::table('users', function (Blueprint $table) {\n            $table->bigInteger('role_id')->change();\n        });\n    }\n}\n"
  },
  {
    "path": "database/migrations/2018_06_24_132346_create_messages_table.php",
    "content": "<?php\n\nuse Illuminate\\Support\\Facades\\Schema;\nuse Illuminate\\Database\\Schema\\Blueprint;\nuse Illuminate\\Database\\Migrations\\Migration;\n\nclass CreateMessagesTable extends Migration\n{\n    /**\n     * Run the migrations.\n     *\n     * @return void\n     */\n    public function up()\n    {\n        Schema::create('messages', function (Blueprint $table) {\n            $table->bigIncrements('auto_id');\n            $table->uuid('id')->index();\n\n            $table->uuid('from_id');\n            $table->uuid('to_id')->nullable();\n\n            $table->text('content');\n            $table->enum('state', ['unread', 'read'])->default('unread');\n\n            $table->timestamps();\n            $table->softDeletes();\n\n            $table->foreign('from_id')->references('id')->on('characters');\n            $table->foreign('to_id')->references('id')->on('characters');\n        });\n    }\n\n    /**\n     * Reverse the migrations.\n     *\n     * @return void\n     */\n    public function down()\n    {\n        Schema::drop('messages');\n    }\n}\n"
  },
  {
    "path": "database/migrations/2018_11_19_202701_create_images.php",
    "content": "<?php\n\nuse Illuminate\\Support\\Facades\\Schema;\nuse Illuminate\\Database\\Schema\\Blueprint;\nuse Illuminate\\Database\\Migrations\\Migration;\n\nclass CreateImages extends Migration\n{\n    /**\n     * Run the migrations.\n     *\n     * @return void\n     */\n    public function up()\n    {\n        Schema::create('images', function (Blueprint $table) {\n            $table->bigIncrements('auto_id');\n            $table->uuid('id')->index();\n\n            $table->uuid('character_id');\n            $table->foreign('character_id')->references('id')->on('characters')->onDelete('restrict');\n\n            $table->string('file_path_full');\n            $table->string('file_path_small');\n            $table->string('file_path_icon');\n\n            $table->timestamps();\n        });\n    }\n\n    /**\n     * Reverse the migrations.\n     *\n     * @return void\n     */\n    public function down()\n    {\n        Schema::dropIfExists('images');\n    }\n}\n"
  },
  {
    "path": "database/migrations/2019_08_19_000000_create_failed_jobs_table.php",
    "content": "<?php\n\nuse Illuminate\\Database\\Migrations\\Migration;\nuse Illuminate\\Database\\Schema\\Blueprint;\nuse Illuminate\\Support\\Facades\\Schema;\n\nclass CreateFailedJobsTable extends Migration\n{\n    /**\n     * Run the migrations.\n     *\n     * @return void\n     */\n    public function up()\n    {\n        Schema::create('failed_jobs', function (Blueprint $table) {\n            $table->id();\n            $table->string('uuid')->unique();\n            $table->text('connection');\n            $table->text('queue');\n            $table->longText('payload');\n            $table->longText('exception');\n            $table->timestamp('failed_at')->useCurrent();\n        });\n    }\n\n    /**\n     * Reverse the migrations.\n     *\n     * @return void\n     */\n    public function down()\n    {\n        Schema::dropIfExists('failed_jobs');\n    }\n}"
  },
  {
    "path": "database/migrations/2019_08_31_182034_create_items_table.php",
    "content": "<?php\n\nuse App\\Models\\ItemPrototype;\nuse App\\Modules\\Equipment\\Application\\Contracts\\ItemPrototypeRepositoryInterface;\nuse App\\Modules\\Equipment\\Domain\\ItemEffect;\nuse App\\Modules\\Equipment\\Domain\\ItemType;\nuse Illuminate\\Support\\Facades\\DB;\nuse Illuminate\\Support\\Facades\\Schema;\nuse Illuminate\\Database\\Schema\\Blueprint;\nuse Illuminate\\Database\\Migrations\\Migration;\n\nclass CreateItemsTable extends Migration\n{\n    /**\n     * Run the migrations.\n     *\n     * @return void\n     *\n     * @throws Exception\n     */\n    public function up()\n    {\n        Schema::create('item_prototypes', static function (Blueprint $table) {\n            $table->bigIncrements('auto_id');\n            $table->uuid('id')->index();\n\n            $table->string('name');\n            $table->string('description');\n\n            $table->json('effects');\n\n            $table->integer('price')->default(0);\n\n            $table->string('image_file_path');\n\n            $table->enum('type', ItemType::TYPES)->default(ItemType::MISCELLANEOUS);\n\n            $table->timestamps();\n        });\n\n        Schema::create('items', static function (Blueprint $table) {\n            $table->uuid('id')->primary();\n\n            $table->string('name');\n            $table->string('description');\n\n            $table->json('effects');\n\n            $table->integer('price')->default(0);\n\n            $table->string('image_file_path');\n\n            $table->enum('type', ItemType::TYPES)->default(ItemType::MISCELLANEOUS);\n\n            $table->uuid('prototype_id');\n            $table->foreign('prototype_id')->references('id')->on('item_prototypes')->onDelete('restrict');\n\n            $table->uuid('creator_character_id');\n            $table->foreign('creator_character_id')->references('id')->on('characters')->onDelete('restrict');\n\n            $table->timestamps();\n        });\n\n        $this->createPrototypes();\n    }\n\n    /**\n     * Reverse the migrations.\n     *\n     * @return void\n     */\n    public function down()\n    {\n        Schema::dropIfExists('items');\n        Schema::dropIfExists('item_prototypes');\n    }\n\n    /**\n     * @return CreateItemsTable\n     * @throws Exception\n     */\n    private function createPrototypes(): self\n    {\n        DB::table('item_prototypes')->delete();\n\n        /** @var ItemPrototypeRepositoryInterface $itemPrototypeRepository */\n        $itemPrototypeRepository = resolve(ItemPrototypeRepositoryInterface::class);\n\n        $prototypes = [\n            [\n                'id' => $itemPrototypeRepository->nextIdentity()->toString(),\n                'name' => 'Wooden Club',\n                'description' => 'Simplest weapon. A crude wooden club made from a peace of wood.',\n                'effects' => [\n                    [\n                        'quantity' => 1,\n                        'type' => ItemEffect::DAMAGE,\n                    ]\n                ],\n                'price' => 15,\n                'type' => ItemType::MAIN_HAND,\n                'image_file_path' => 'images/equipment/main_hand/1club.png',\n            ],\n            [\n                'id' => $itemPrototypeRepository->nextIdentity()->toString(),\n                'name' => 'Reinforced Club',\n                'description' => 'A wooden club reinforced with metal.',\n                'effects' => [\n                    [\n                        'quantity' => 3,\n                        'type' => ItemEffect::DAMAGE,\n                    ]\n                ],\n                'price' => 500,\n                'type' => ItemType::MAIN_HAND,\n                'image_file_path' => 'images/equipment/main_hand/2reinforced_club.png',\n            ],\n            [\n                'id' => $itemPrototypeRepository->nextIdentity()->toString(),\n                'name' => 'Wooden Buckler',\n                'description' => 'A small wooden shield.',\n                'effects' => [\n                    [\n                        'quantity' => 2,\n                        'type' => ItemEffect::ARMOR,\n                    ]\n                ],\n                'price' => 20,\n                'type' => ItemType::OFF_HAND,\n                'image_file_path' => 'images/equipment/off_hand/buckler.png',\n            ],\n            [\n                'id' => $itemPrototypeRepository->nextIdentity()->toString(),\n                'name' => 'Linen Shirt',\n                'description' => 'A simple shirt made of linen.',\n                'effects' => [\n                    [\n                        'quantity' => 1,\n                        'type' => ItemEffect::ARMOR,\n                    ]\n                ],\n                'price' => 5,\n                'type' => ItemType::BODY_ARMOR,\n                'image_file_path' => 'images/equipment/body_armor/linen_shirt.png',\n            ],\n            [\n                'id' => $itemPrototypeRepository->nextIdentity()->toString(),\n                'name' => 'Closed Steel Helmet',\n                'description' => 'Closed helmet made of steel plates',\n                'effects' => [\n                    [\n                        'quantity' => 10,\n                        'type' => ItemEffect::ARMOR,\n                    ]\n                ],\n                'price' => 1000,\n                'type' => ItemType::HEAD_GEAR,\n                'image_file_path' => 'images/equipment/head_gear/closed_steel_helmet.png',\n            ],\n        ];\n\n        foreach ($prototypes as $prototype) {\n            ItemPrototype::query()->create($prototype);\n        }\n\n        return $this;\n    }\n}\n"
  },
  {
    "path": "database/migrations/2020_02_29_205331_create_inventories.php",
    "content": "<?php\n\nuse Illuminate\\Database\\Migrations\\Migration;\nuse Illuminate\\Database\\Schema\\Blueprint;\nuse Illuminate\\Support\\Facades\\Schema;\n\nclass CreateInventories extends Migration\n{\n    /**\n     * Run the migrations.\n     *\n     * @return void\n     */\n    public function up()\n    {\n        Schema::create('inventories', function (Blueprint $table) {\n            $table->bigIncrements('auto_id');\n            $table->uuid('id')->index();\n\n            $table->uuid('character_id')->nullable();\n            // TODO: refactor character creation to allow creating character record before inventory record\n            // $table->foreign('character_id')->references('id')->on('characters')->onDelete('restrict');\n\n            $table->integer('money');\n\n            $table->timestamps();\n        });\n    }\n\n    /**\n     * Reverse the migrations.\n     *\n     * @return void\n     */\n    public function down()\n    {\n        Schema::dropIfExists('inventories');\n    }\n}\n"
  },
  {
    "path": "database/migrations/2020_02_29_205957_create_inventory_item.php",
    "content": "<?php\n\nuse App\\Modules\\Equipment\\Domain\\ItemStatus;\nuse Illuminate\\Database\\Migrations\\Migration;\nuse Illuminate\\Database\\Schema\\Blueprint;\nuse Illuminate\\Support\\Facades\\Schema;\n\nclass CreateInventoryItem extends Migration\n{\n    /**\n     * Run the migrations.\n     *\n     * @return void\n     */\n    public function up()\n    {\n        Schema::create('inventory_item', static function (Blueprint $table) {\n\n            $table->smallInteger('inventory_slot_number');\n\n            $table->enum('status', ItemStatus::STATUSES)->default(ItemStatus::IN_BACKPACK);\n\n            $table->uuid('inventory_id')->index();\n            $table->foreign('inventory_id')->references('id')->on('inventories')->onDelete('cascade');\n\n            $table->uuid('item_id')->index();\n            $table->foreign('item_id')->references('id')->on('items')->onDelete('cascade');\n\n            $table->timestamps();\n        });\n    }\n\n    /**\n     * Reverse the migrations.\n     *\n     * @return void\n     */\n    public function down()\n    {\n        Schema::dropIfExists('inventory_item');\n    }\n}\n"
  },
  {
    "path": "database/migrations/2020_03_30_133100_create_stores.php",
    "content": "<?php\n\nuse App\\Modules\\Trade\\Domain\\StoreType;\nuse Illuminate\\Database\\Migrations\\Migration;\nuse Illuminate\\Database\\Schema\\Blueprint;\nuse Illuminate\\Support\\Facades\\Schema;\n\nclass CreateStores extends Migration\n{\n    /**\n     * Run the migrations.\n     *\n     * @return void\n     */\n    public function up()\n    {\n        Schema::create('stores', static function (Blueprint $table) {\n            $table->bigIncrements('auto_id');\n            $table->uuid('id')->index();\n\n            $table->enum('type', StoreType::TYPES)->default(StoreType::SELL_ONLY);\n\n            $table->uuid('character_id')->nullable();\n            $table->foreign('character_id')->references('id')->on('characters')->onDelete('restrict');\n\n            $table->integer('money');\n\n            $table->timestamps();\n        });\n    }\n\n    /**\n     * Reverse the migrations.\n     *\n     * @return void\n     */\n    public function down()\n    {\n        Schema::dropIfExists('stores');\n    }\n}\n"
  },
  {
    "path": "database/migrations/2020_03_30_133448_create_store_item.php",
    "content": "<?php\n\nuse Illuminate\\Database\\Migrations\\Migration;\nuse Illuminate\\Database\\Schema\\Blueprint;\nuse Illuminate\\Support\\Facades\\Schema;\n\nclass CreateStoreItem extends Migration\n{\n    /**\n     * Run the migrations.\n     *\n     * @return void\n     */\n    public function up()\n    {\n        Schema::create('store_item', static function (Blueprint $table) {\n\n            $table->smallInteger('inventory_slot_number');\n\n            $table->integer('price')->default(0);\n\n            $table->uuid('store_id')->index();\n            $table->foreign('store_id')->references('id')->on('stores')->onDelete('cascade');\n\n            $table->uuid('item_id')->index();\n            $table->foreign('item_id')->references('id')->on('items')->onDelete('cascade');\n\n            $table->timestamps();\n        });\n    }\n\n    /**\n     * Reverse the migrations.\n     *\n     * @return void\n     */\n    public function down()\n    {\n        Schema::dropIfExists('store_item');\n    }\n}\n"
  },
  {
    "path": "database/seeders/CharacterSeeder.php",
    "content": "<?php\n\nnamespace Database\\Seeders;\n\nuse App\\Models\\Character;\nuse App\\Models\\Inventory;\nuse App\\Models\\Item;\nuse App\\Models\\ItemPrototype;\nuse App\\Models\\Location;\nuse App\\Modules\\Character\\Application\\Contracts\\CharacterRepositoryInterface;\nuse App\\Modules\\Character\\Domain\\CharacterType;\nuse App\\Modules\\Equipment\\Application\\Contracts\\InventoryRepositoryInterface;\nuse App\\Modules\\Equipment\\Application\\Contracts\\ItemRepositoryInterface;\nuse App\\Modules\\Equipment\\Domain\\ItemStatus;\nuse App\\Modules\\Trade\\Application\\Contracts\\StoreRepositoryInterface;\nuse App\\Models\\Store;\nuse App\\Models\\User;\nuse Illuminate\\Database\\Seeder;\n\nclass CharacterSeeder extends Seeder\n{\n    /**\n     * Run the database seeders.\n     *\n     * @return void\n     */\n    public function run()\n    {\n        if (Character::query()->count())\n        {\n            return;\n        }\n\n        /** @var CharacterRepositoryInterface $characterRepository */\n        $characterRepository = resolve(CharacterRepositoryInterface::class);\n\n        /** @var InventoryRepositoryInterface $inventoryRepository */\n        $inventoryRepository = resolve(InventoryRepositoryInterface::class);\n\n        /** @var StoreRepositoryInterface $storeRepository */\n        $storeRepository = resolve(StoreRepositoryInterface::class);\n\n        /** @var ItemRepositoryInterface $itemRepository */\n        $itemRepository = resolve(ItemRepositoryInterface::class);\n\n        $totalHitPoints = 100;\n\n        /** @var User $user */\n        $user = User::query()->first();\n\n        /** @var Location $location */\n        $location = Location::query()->firstOrFail();\n\n        /** @var Character $someone */\n        $someone = Character::query()->create([\n            'id' => $characterRepository->nextIdentity()->toString(),\n            'name' => 'Someone',\n            'gender' => 'male',\n            'type' => CharacterType::PLAYER,\n\n            'xp' => 0,\n            'reputation' => 0,\n            'hit_points' => $totalHitPoints,\n            'total_hit_points' => $totalHitPoints,\n\n            'strength' => 5,\n            'agility' => 5,\n            'constitution' => 5,\n            'intelligence' => 5,\n            'charisma' => 1,\n\n            'level_id' => 1,\n            'user_id' => $user->getId(),\n            'location_id' => $location->getId(),\n            'race_id' => 1,\n        ]);\n\n        /** @var Inventory $inventory */\n        $inventory = Inventory::query()->create([\n            'id' => $inventoryRepository->nextIdentity()->toString(),\n            'character_id' => $someone->getId(),\n            'money' => 100,\n        ]);\n\n        Store::query()->create([\n            'id' => $storeRepository->nextIdentity()->toString(),\n            'character_id' => $someone->getId(),\n            'money' => 1000,\n        ]);\n\n        ItemPrototype::query()->get()\n            ->each(static function (ItemPrototype $weaponPrototype, int $slot) use ($someone, $inventory, $itemRepository) {\n\n                /** @var Item $item */\n                $item = Item::query()->create([\n                    'id' => $itemRepository->nextIdentity()->toString(),\n                    'name' => $weaponPrototype->getName(),\n                    'description' => $weaponPrototype->getDescription(),\n                    'effects' => $weaponPrototype->getEffects(),\n                    'price' => $weaponPrototype->getPrice(),\n                    'type' => $weaponPrototype->getType(),\n                    'image_file_path' => $weaponPrototype->getImageFilePath(),\n                    'prototype_id' => $weaponPrototype->getId(),\n                    'creator_character_id' => $someone->getId(),\n                ]);\n\n                $inventory->items()->attach($item->getId(), [\n                    'inventory_slot_number' => $slot,\n                    'status' => $slot ? ItemStatus::IN_BACKPACK : ItemStatus::EQUIPPED,\n                ]);\n            });\n\n        factory(Character::class, 50)->create();\n        factory(Item::class, 50)->create();\n    }\n}\n"
  },
  {
    "path": "database/seeders/DataRowsTableSeeder.php",
    "content": "<?php\n\nnamespace Database\\Seeders;\n\nuse Illuminate\\Database\\Seeder;\nuse TCG\\Voyager\\Models\\DataRow;\nuse TCG\\Voyager\\Models\\DataType;\n\nclass DataRowsTableSeeder extends Seeder\n{\n    /**\n     * Auto generated seed file.\n     */\n    public function run()\n    {\n        $userDataType = DataType::where('slug', 'users')->firstOrFail();\n        $menuDataType = DataType::where('slug', 'menus')->firstOrFail();\n        $roleDataType = DataType::where('slug', 'roles')->firstOrFail();\n\n        $dataRow = $this->dataRow($userDataType, 'id');\n        if (!$dataRow->exists) {\n            $dataRow->fill([\n                'type'         => 'number',\n                'display_name' => __('voyager::seeders.data_rows.id'),\n                'required'     => 1,\n                'browse'       => 0,\n                'read'         => 0,\n                'edit'         => 0,\n                'add'          => 0,\n                'delete'       => 0,\n                'order'        => 1,\n            ])->save();\n        }\n\n        $dataRow = $this->dataRow($userDataType, 'name');\n        if (!$dataRow->exists) {\n            $dataRow->fill([\n                'type'         => 'text',\n                'display_name' => __('voyager::seeders.data_rows.name'),\n                'required'     => 1,\n                'browse'       => 1,\n                'read'         => 1,\n                'edit'         => 1,\n                'add'          => 1,\n                'delete'       => 1,\n                'order'        => 2,\n            ])->save();\n        }\n\n        $dataRow = $this->dataRow($userDataType, 'email');\n        if (!$dataRow->exists) {\n            $dataRow->fill([\n                'type'         => 'text',\n                'display_name' => __('voyager::seeders.data_rows.email'),\n                'required'     => 1,\n                'browse'       => 1,\n                'read'         => 1,\n                'edit'         => 1,\n                'add'          => 1,\n                'delete'       => 1,\n                'order'        => 3,\n            ])->save();\n        }\n\n        $dataRow = $this->dataRow($userDataType, 'password');\n        if (!$dataRow->exists) {\n            $dataRow->fill([\n                'type'         => 'password',\n                'display_name' => __('voyager::seeders.data_rows.password'),\n                'required'     => 1,\n                'browse'       => 0,\n                'read'         => 0,\n                'edit'         => 1,\n                'add'          => 1,\n                'delete'       => 0,\n                'order'        => 4,\n            ])->save();\n        }\n\n        $dataRow = $this->dataRow($userDataType, 'remember_token');\n        if (!$dataRow->exists) {\n            $dataRow->fill([\n                'type'         => 'text',\n                'display_name' => __('voyager::seeders.data_rows.remember_token'),\n                'required'     => 0,\n                'browse'       => 0,\n                'read'         => 0,\n                'edit'         => 0,\n                'add'          => 0,\n                'delete'       => 0,\n                'order'        => 5,\n            ])->save();\n        }\n\n        $dataRow = $this->dataRow($userDataType, 'created_at');\n        if (!$dataRow->exists) {\n            $dataRow->fill([\n                'type'         => 'timestamp',\n                'display_name' => __('voyager::seeders.data_rows.created_at'),\n                'required'     => 0,\n                'browse'       => 1,\n                'read'         => 1,\n                'edit'         => 0,\n                'add'          => 0,\n                'delete'       => 0,\n                'order'        => 6,\n            ])->save();\n        }\n\n        $dataRow = $this->dataRow($userDataType, 'updated_at');\n        if (!$dataRow->exists) {\n            $dataRow->fill([\n                'type'         => 'timestamp',\n                'display_name' => __('voyager::seeders.data_rows.updated_at'),\n                'required'     => 0,\n                'browse'       => 0,\n                'read'         => 0,\n                'edit'         => 0,\n                'add'          => 0,\n                'delete'       => 0,\n                'order'        => 7,\n            ])->save();\n        }\n\n        $dataRow = $this->dataRow($userDataType, 'avatar');\n        if (!$dataRow->exists) {\n            $dataRow->fill([\n                'type'         => 'image',\n                'display_name' => __('voyager::seeders.data_rows.avatar'),\n                'required'     => 0,\n                'browse'       => 1,\n                'read'         => 1,\n                'edit'         => 1,\n                'add'          => 1,\n                'delete'       => 1,\n                'order'        => 8,\n            ])->save();\n        }\n\n        $dataRow = $this->dataRow($userDataType, 'user_belongsto_role_relationship');\n        if (!$dataRow->exists) {\n            $dataRow->fill([\n                'type'         => 'relationship',\n                'display_name' => __('voyager::seeders.data_rows.role'),\n                'required'     => 0,\n                'browse'       => 1,\n                'read'         => 1,\n                'edit'         => 1,\n                'add'          => 1,\n                'delete'       => 0,\n                'details'      => [\n                    'model'       => 'TCG\\\\Voyager\\\\Models\\\\Role',\n                    'table'       => 'roles',\n                    'type'        => 'belongsTo',\n                    'column'      => 'role_id',\n                    'key'         => 'id',\n                    'label'       => 'display_name',\n                    'pivot_table' => 'roles',\n                    'pivot'       => 0,\n                ],\n                'order'        => 10,\n            ])->save();\n        }\n\n        $dataRow = $this->dataRow($userDataType, 'user_belongstomany_role_relationship');\n        if (!$dataRow->exists) {\n            $dataRow->fill([\n                'type'         => 'relationship',\n                'display_name' => 'Roles',\n                'required'     => 0,\n                'browse'       => 1,\n                'read'         => 1,\n                'edit'         => 1,\n                'add'          => 1,\n                'delete'       => 0,\n                'details'      => [\n                    'model'       => 'TCG\\\\Voyager\\\\Models\\\\Role',\n                    'table'       => 'roles',\n                    'type'        => 'belongsToMany',\n                    'column'      => 'id',\n                    'key'         => 'id',\n                    'label'       => 'display_name',\n                    'pivot_table' => 'user_roles',\n                    'pivot'       => '1',\n                    'taggable'    => '0',\n                ],\n                'order'        => 11,\n            ])->save();\n        }\n\n        $dataRow = $this->dataRow($userDataType, 'settings');\n        if (!$dataRow->exists) {\n            $dataRow->fill([\n                'type'         => 'hidden',\n                'display_name' => 'Settings',\n                'required'     => 0,\n                'browse'       => 0,\n                'read'         => 0,\n                'edit'         => 0,\n                'add'          => 0,\n                'delete'       => 0,\n                'order'        => 12,\n            ])->save();\n        }\n\n        $dataRow = $this->dataRow($menuDataType, 'id');\n        if (!$dataRow->exists) {\n            $dataRow->fill([\n                'type'         => 'number',\n                'display_name' => __('voyager::seeders.data_rows.id'),\n                'required'     => 1,\n                'browse'       => 0,\n                'read'         => 0,\n                'edit'         => 0,\n                'add'          => 0,\n                'delete'       => 0,\n                'order'        => 1,\n            ])->save();\n        }\n\n        $dataRow = $this->dataRow($menuDataType, 'name');\n        if (!$dataRow->exists) {\n            $dataRow->fill([\n                'type'         => 'text',\n                'display_name' => __('voyager::seeders.data_rows.name'),\n                'required'     => 1,\n                'browse'       => 1,\n                'read'         => 1,\n                'edit'         => 1,\n                'add'          => 1,\n                'delete'       => 1,\n                'order'        => 2,\n            ])->save();\n        }\n\n        $dataRow = $this->dataRow($menuDataType, 'created_at');\n        if (!$dataRow->exists) {\n            $dataRow->fill([\n                'type'         => 'timestamp',\n                'display_name' => __('voyager::seeders.data_rows.created_at'),\n                'required'     => 0,\n                'browse'       => 0,\n                'read'         => 0,\n                'edit'         => 0,\n                'add'          => 0,\n                'delete'       => 0,\n                'order'        => 3,\n            ])->save();\n        }\n\n        $dataRow = $this->dataRow($menuDataType, 'updated_at');\n        if (!$dataRow->exists) {\n            $dataRow->fill([\n                'type'         => 'timestamp',\n                'display_name' => __('voyager::seeders.data_rows.updated_at'),\n                'required'     => 0,\n                'browse'       => 0,\n                'read'         => 0,\n                'edit'         => 0,\n                'add'          => 0,\n                'delete'       => 0,\n                'order'        => 4,\n            ])->save();\n        }\n\n        $dataRow = $this->dataRow($roleDataType, 'id');\n        if (!$dataRow->exists) {\n            $dataRow->fill([\n                'type'         => 'number',\n                'display_name' => __('voyager::seeders.data_rows.id'),\n                'required'     => 1,\n                'browse'       => 0,\n                'read'         => 0,\n                'edit'         => 0,\n                'add'          => 0,\n                'delete'       => 0,\n                'order'        => 1,\n            ])->save();\n        }\n\n        $dataRow = $this->dataRow($roleDataType, 'name');\n        if (!$dataRow->exists) {\n            $dataRow->fill([\n                'type'         => 'text',\n                'display_name' => __('voyager::seeders.data_rows.name'),\n                'required'     => 1,\n                'browse'       => 1,\n                'read'         => 1,\n                'edit'         => 1,\n                'add'          => 1,\n                'delete'       => 1,\n                'order'        => 2,\n            ])->save();\n        }\n\n        $dataRow = $this->dataRow($roleDataType, 'created_at');\n        if (!$dataRow->exists) {\n            $dataRow->fill([\n                'type'         => 'timestamp',\n                'display_name' => __('voyager::seeders.data_rows.created_at'),\n                'required'     => 0,\n                'browse'       => 0,\n                'read'         => 0,\n                'edit'         => 0,\n                'add'          => 0,\n                'delete'       => 0,\n                'order'        => 3,\n            ])->save();\n        }\n\n        $dataRow = $this->dataRow($roleDataType, 'updated_at');\n        if (!$dataRow->exists) {\n            $dataRow->fill([\n                'type'         => 'timestamp',\n                'display_name' => __('voyager::seeders.data_rows.updated_at'),\n                'required'     => 0,\n                'browse'       => 0,\n                'read'         => 0,\n                'edit'         => 0,\n                'add'          => 0,\n                'delete'       => 0,\n                'order'        => 4,\n            ])->save();\n        }\n\n        $dataRow = $this->dataRow($roleDataType, 'display_name');\n        if (!$dataRow->exists) {\n            $dataRow->fill([\n                'type'         => 'text',\n                'display_name' => __('voyager::seeders.data_rows.display_name'),\n                'required'     => 1,\n                'browse'       => 1,\n                'read'         => 1,\n                'edit'         => 1,\n                'add'          => 1,\n                'delete'       => 1,\n                'order'        => 5,\n            ])->save();\n        }\n\n        $dataRow = $this->dataRow($userDataType, 'role_id');\n        if (!$dataRow->exists) {\n            $dataRow->fill([\n                'type'         => 'text',\n                'display_name' => __('voyager::seeders.data_rows.role'),\n                'required'     => 1,\n                'browse'       => 1,\n                'read'         => 1,\n                'edit'         => 1,\n                'add'          => 1,\n                'delete'       => 1,\n                'order'        => 9,\n            ])->save();\n        }\n    }\n\n    /**\n     * [dataRow description].\n     *\n     * @param [type] $type  [description]\n     * @param [type] $field [description]\n     *\n     * @return [type] [description]\n     */\n    protected function dataRow($type, $field)\n    {\n        return DataRow::firstOrNew([\n            'data_type_id' => $type->id,\n            'field'        => $field,\n        ]);\n    }\n}\n"
  },
  {
    "path": "database/seeders/DataTypesTableSeeder.php",
    "content": "<?php\n\nnamespace Database\\Seeders;\n\nuse Illuminate\\Database\\Seeder;\nuse TCG\\Voyager\\Models\\DataType;\n\nclass DataTypesTableSeeder extends Seeder\n{\n    /**\n     * Auto generated seed file.\n     */\n    public function run()\n    {\n        $dataType = $this->dataType('slug', 'users');\n        if (!$dataType->exists) {\n            $dataType->fill([\n                'name'                  => 'users',\n                'display_name_singular' => __('voyager::seeders.data_types.user.singular'),\n                'display_name_plural'   => __('voyager::seeders.data_types.user.plural'),\n                'icon'                  => 'voyager-person',\n                'model_name'            => 'TCG\\\\Voyager\\\\Models\\\\User',\n                'policy_name'           => 'TCG\\\\Voyager\\\\Policies\\\\UserPolicy',\n                'controller'            => 'TCG\\\\Voyager\\\\Http\\\\Controllers\\\\VoyagerUserController',\n                'generate_permissions'  => 1,\n                'description'           => '',\n            ])->save();\n        }\n\n        $dataType = $this->dataType('slug', 'menus');\n        if (!$dataType->exists) {\n            $dataType->fill([\n                'name'                  => 'menus',\n                'display_name_singular' => __('voyager::seeders.data_types.menu.singular'),\n                'display_name_plural'   => __('voyager::seeders.data_types.menu.plural'),\n                'icon'                  => 'voyager-list',\n                'model_name'            => 'TCG\\\\Voyager\\\\Models\\\\Menu',\n                'controller'            => '',\n                'generate_permissions'  => 1,\n                'description'           => '',\n            ])->save();\n        }\n\n        $dataType = $this->dataType('slug', 'roles');\n        if (!$dataType->exists) {\n            $dataType->fill([\n                'name'                  => 'roles',\n                'display_name_singular' => __('voyager::seeders.data_types.role.singular'),\n                'display_name_plural'   => __('voyager::seeders.data_types.role.plural'),\n                'icon'                  => 'voyager-lock',\n                'model_name'            => 'TCG\\\\Voyager\\\\Models\\\\Role',\n                'controller'            => '',\n                'generate_permissions'  => 1,\n                'description'           => '',\n            ])->save();\n        }\n    }\n\n    /**\n     * [dataType description].\n     *\n     * @param [type] $field [description]\n     * @param [type] $for   [description]\n     *\n     * @return [type] [description]\n     */\n    protected function dataType($field, $for)\n    {\n        return DataType::firstOrNew([$field => $for]);\n    }\n}\n"
  },
  {
    "path": "database/seeders/DatabaseSeeder.php",
    "content": "<?php\n\nnamespace Database\\Seeders;\n\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Illuminate\\Database\\Seeder;\n\nclass DatabaseSeeder extends Seeder\n{\n    /**\n     * Run the database seeders.\n     *\n     * @return void\n     */\n    public function run()\n    {\n        Model::unguard();\n\n        $this->call(UserSeeder::class);\n        $this->call(CharacterSeeder::class);\n        $this->call(VoyagerDatabaseSeeder::class);\n\n        Model::reguard();\n    }\n}\n"
  },
  {
    "path": "database/seeders/MenuItemsTableSeeder.php",
    "content": "<?php\n\nnamespace Database\\Seeders;\n\nuse Illuminate\\Database\\Seeder;\nuse TCG\\Voyager\\Models\\Menu;\nuse TCG\\Voyager\\Models\\MenuItem;\n\nclass MenuItemsTableSeeder extends Seeder\n{\n    /**\n     * Auto generated seed file.\n     *\n     * @return void\n     */\n    public function run()\n    {\n        $menu = Menu::where('name', 'admin')->firstOrFail();\n\n        $menuItem = MenuItem::firstOrNew([\n            'menu_id' => $menu->id,\n            'title'   => __('voyager::seeders.menu_items.dashboard'),\n            'url'     => '',\n            'route'   => 'voyager.dashboard',\n        ]);\n        if (!$menuItem->exists) {\n            $menuItem->fill([\n                'target'     => '_self',\n                'icon_class' => 'voyager-boat',\n                'color'      => null,\n                'parent_id'  => null,\n                'order'      => 1,\n            ])->save();\n        }\n\n        $menuItem = MenuItem::firstOrNew([\n            'menu_id' => $menu->id,\n            'title'   => __('voyager::seeders.menu_items.media'),\n            'url'     => '',\n            'route'   => 'voyager.media.index',\n        ]);\n        if (!$menuItem->exists) {\n            $menuItem->fill([\n                'target'     => '_self',\n                'icon_class' => 'voyager-images',\n                'color'      => null,\n                'parent_id'  => null,\n                'order'      => 5,\n            ])->save();\n        }\n\n        $menuItem = MenuItem::firstOrNew([\n            'menu_id' => $menu->id,\n            'title'   => __('voyager::seeders.menu_items.users'),\n            'url'     => '',\n            'route'   => 'voyager.users.index',\n        ]);\n        if (!$menuItem->exists) {\n            $menuItem->fill([\n                'target'     => '_self',\n                'icon_class' => 'voyager-person',\n                'color'      => null,\n                'parent_id'  => null,\n                'order'      => 3,\n            ])->save();\n        }\n\n        $menuItem = MenuItem::firstOrNew([\n            'menu_id' => $menu->id,\n            'title'   => __('voyager::seeders.menu_items.roles'),\n            'url'     => '',\n            'route'   => 'voyager.roles.index',\n        ]);\n        if (!$menuItem->exists) {\n            $menuItem->fill([\n                'target'     => '_self',\n                'icon_class' => 'voyager-lock',\n                'color'      => null,\n                'parent_id'  => null,\n                'order'      => 2,\n            ])->save();\n        }\n\n        $toolsMenuItem = MenuItem::firstOrNew([\n            'menu_id' => $menu->id,\n            'title'   => __('voyager::seeders.menu_items.tools'),\n            'url'     => '',\n        ]);\n        if (!$toolsMenuItem->exists) {\n            $toolsMenuItem->fill([\n                'target'     => '_self',\n                'icon_class' => 'voyager-tools',\n                'color'      => null,\n                'parent_id'  => null,\n                'order'      => 9,\n            ])->save();\n        }\n\n        $menuItem = MenuItem::firstOrNew([\n            'menu_id' => $menu->id,\n            'title'   => __('voyager::seeders.menu_items.menu_builder'),\n            'url'     => '',\n            'route'   => 'voyager.menus.index',\n        ]);\n        if (!$menuItem->exists) {\n            $menuItem->fill([\n                'target'     => '_self',\n                'icon_class' => 'voyager-list',\n                'color'      => null,\n                'parent_id'  => $toolsMenuItem->id,\n                'order'      => 10,\n            ])->save();\n        }\n\n        $menuItem = MenuItem::firstOrNew([\n            'menu_id' => $menu->id,\n            'title'   => __('voyager::seeders.menu_items.database'),\n            'url'     => '',\n            'route'   => 'voyager.database.index',\n        ]);\n        if (!$menuItem->exists) {\n            $menuItem->fill([\n                'target'     => '_self',\n                'icon_class' => 'voyager-data',\n                'color'      => null,\n                'parent_id'  => $toolsMenuItem->id,\n                'order'      => 11,\n            ])->save();\n        }\n\n        $menuItem = MenuItem::firstOrNew([\n            'menu_id' => $menu->id,\n            'title'   => __('voyager::seeders.menu_items.compass'),\n            'url'     => '',\n            'route'   => 'voyager.compass.index',\n        ]);\n        if (!$menuItem->exists) {\n            $menuItem->fill([\n                'target'     => '_self',\n                'icon_class' => 'voyager-compass',\n                'color'      => null,\n                'parent_id'  => $toolsMenuItem->id,\n                'order'      => 12,\n            ])->save();\n        }\n\n        $menuItem = MenuItem::firstOrNew([\n            'menu_id' => $menu->id,\n            'title'   => __('voyager::seeders.menu_items.bread'),\n            'url'     => '',\n            'route'   => 'voyager.bread.index',\n        ]);\n        if (!$menuItem->exists) {\n            $menuItem->fill([\n                'target'     => '_self',\n                'icon_class' => 'voyager-bread',\n                'color'      => null,\n                'parent_id'  => $toolsMenuItem->id,\n                'order'      => 13,\n            ])->save();\n        }\n\n        $menuItem = MenuItem::firstOrNew([\n            'menu_id' => $menu->id,\n            'title'   => __('voyager::seeders.menu_items.settings'),\n            'url'     => '',\n            'route'   => 'voyager.settings.index',\n        ]);\n        if (!$menuItem->exists) {\n            $menuItem->fill([\n                'target'     => '_self',\n                'icon_class' => 'voyager-settings',\n                'color'      => null,\n                'parent_id'  => null,\n                'order'      => 14,\n            ])->save();\n        }\n    }\n}\n"
  },
  {
    "path": "database/seeders/MenusTableSeeder.php",
    "content": "<?php\n\nnamespace Database\\Seeders;\n\nuse Illuminate\\Database\\Seeder;\nuse TCG\\Voyager\\Models\\Menu;\n\nclass MenusTableSeeder extends Seeder\n{\n    /**\n     * Auto generated seed file.\n     *\n     * @return void\n     */\n    public function run()\n    {\n        Menu::firstOrCreate([\n            'name' => 'admin',\n        ]);\n    }\n}\n"
  },
  {
    "path": "database/seeders/PermissionRoleTableSeeder.php",
    "content": "<?php\n\nnamespace Database\\Seeders;\n\nuse Illuminate\\Database\\Seeder;\nuse TCG\\Voyager\\Models\\Permission;\nuse TCG\\Voyager\\Models\\Role;\n\nclass PermissionRoleTableSeeder extends Seeder\n{\n    /**\n     * Auto generated seed file.\n     *\n     * @return void\n     */\n    public function run()\n    {\n        $role = Role::where('name', 'admin')->firstOrFail();\n\n        $permissions = Permission::all();\n\n        $role->permissions()->sync(\n            $permissions->pluck('id')->all()\n        );\n    }\n}\n"
  },
  {
    "path": "database/seeders/PermissionsTableSeeder.php",
    "content": "<?php\n\nnamespace Database\\Seeders;\n\nuse Illuminate\\Database\\Seeder;\nuse TCG\\Voyager\\Models\\Permission;\n\nclass PermissionsTableSeeder extends Seeder\n{\n    /**\n     * Auto generated seed file.\n     */\n    public function run()\n    {\n        $keys = [\n            'browse_admin',\n            'browse_bread',\n            'browse_database',\n            'browse_media',\n            'browse_compass',\n        ];\n\n        foreach ($keys as $key) {\n            Permission::firstOrCreate([\n                'key'        => $key,\n                'table_name' => null,\n            ]);\n        }\n\n        Permission::generateFor('menus');\n\n        Permission::generateFor('roles');\n\n        Permission::generateFor('users');\n\n        Permission::generateFor('settings');\n    }\n}\n"
  },
  {
    "path": "database/seeders/RolesTableSeeder.php",
    "content": "<?php\n\nnamespace Database\\Seeders;\n\nuse Illuminate\\Database\\Seeder;\nuse TCG\\Voyager\\Models\\Role;\n\nclass RolesTableSeeder extends Seeder\n{\n    /**\n     * Auto generated seed file.\n     */\n    public function run()\n    {\n        $role = Role::firstOrNew(['name' => 'admin']);\n        if (!$role->exists) {\n            $role->fill([\n                    'display_name' => __('voyager::seeders.roles.admin'),\n                ])->save();\n        }\n\n        $role = Role::firstOrNew(['name' => 'user']);\n        if (!$role->exists) {\n            $role->fill([\n                    'display_name' => __('voyager::seeders.roles.user'),\n                ])->save();\n        }\n    }\n}\n"
  },
  {
    "path": "database/seeders/SettingsTableSeeder.php",
    "content": "<?php\n\nnamespace Database\\Seeders;\n\nuse Illuminate\\Database\\Seeder;\nuse TCG\\Voyager\\Models\\Setting;\n\nclass SettingsTableSeeder extends Seeder\n{\n    /**\n     * Auto generated seed file.\n     */\n    public function run()\n    {\n        $setting = $this->findSetting('site.title');\n        if (!$setting->exists) {\n            $setting->fill([\n                'display_name' => __('voyager::seeders.settings.site.title'),\n                'value'        => __('voyager::seeders.settings.site.title'),\n                'details'      => '',\n                'type'         => 'text',\n                'order'        => 1,\n                'group'        => 'Site',\n            ])->save();\n        }\n\n        $setting = $this->findSetting('site.description');\n        if (!$setting->exists) {\n            $setting->fill([\n                'display_name' => __('voyager::seeders.settings.site.description'),\n                'value'        => __('voyager::seeders.settings.site.description'),\n                'details'      => '',\n                'type'         => 'text',\n                'order'        => 2,\n                'group'        => 'Site',\n            ])->save();\n        }\n\n        $setting = $this->findSetting('site.logo');\n        if (!$setting->exists) {\n            $setting->fill([\n                'display_name' => __('voyager::seeders.settings.site.logo'),\n                'value'        => '',\n                'details'      => '',\n                'type'         => 'image',\n                'order'        => 3,\n                'group'        => 'Site',\n            ])->save();\n        }\n\n        $setting = $this->findSetting('site.google_analytics_tracking_id');\n        if (!$setting->exists) {\n            $setting->fill([\n                'display_name' => __('voyager::seeders.settings.site.google_analytics_tracking_id'),\n                'value'        => '',\n                'details'      => '',\n                'type'         => 'text',\n                'order'        => 4,\n                'group'        => 'Site',\n            ])->save();\n        }\n\n        $setting = $this->findSetting('admin.bg_image');\n        if (!$setting->exists) {\n            $setting->fill([\n                'display_name' => __('voyager::seeders.settings.admin.background_image'),\n                'value'        => '',\n                'details'      => '',\n                'type'         => 'image',\n                'order'        => 5,\n                'group'        => 'Admin',\n            ])->save();\n        }\n\n        $setting = $this->findSetting('admin.title');\n        if (!$setting->exists) {\n            $setting->fill([\n                'display_name' => __('voyager::seeders.settings.admin.title'),\n                'value'        => 'Voyager',\n                'details'      => '',\n                'type'         => 'text',\n                'order'        => 1,\n                'group'        => 'Admin',\n            ])->save();\n        }\n\n        $setting = $this->findSetting('admin.description');\n        if (!$setting->exists) {\n            $setting->fill([\n                'display_name' => __('voyager::seeders.settings.admin.description'),\n                'value'        => __('voyager::seeders.settings.admin.description_value'),\n                'details'      => '',\n                'type'         => 'text',\n                'order'        => 2,\n                'group'        => 'Admin',\n            ])->save();\n        }\n\n        $setting = $this->findSetting('admin.loader');\n        if (!$setting->exists) {\n            $setting->fill([\n                'display_name' => __('voyager::seeders.settings.admin.loader'),\n                'value'        => '',\n                'details'      => '',\n                'type'         => 'image',\n                'order'        => 3,\n                'group'        => 'Admin',\n            ])->save();\n        }\n\n        $setting = $this->findSetting('admin.icon_image');\n        if (!$setting->exists) {\n            $setting->fill([\n                'display_name' => __('voyager::seeders.settings.admin.icon_image'),\n                'value'        => '',\n                'details'      => '',\n                'type'         => 'image',\n                'order'        => 4,\n                'group'        => 'Admin',\n            ])->save();\n        }\n\n        $setting = $this->findSetting('admin.google_analytics_client_id');\n        if (!$setting->exists) {\n            $setting->fill([\n                'display_name' => __('voyager::seeders.settings.admin.google_analytics_client_id'),\n                'value'        => '',\n                'details'      => '',\n                'type'         => 'text',\n                'order'        => 1,\n                'group'        => 'Admin',\n            ])->save();\n        }\n    }\n\n    /**\n     * [setting description].\n     *\n     * @param [type] $key [description]\n     *\n     * @return [type] [description]\n     */\n    protected function findSetting($key)\n    {\n        return Setting::firstOrNew(['key' => $key]);\n    }\n}\n"
  },
  {
    "path": "database/seeders/TranslationsTableSeeder.php",
    "content": "<?php\n\nnamespace Database\\Seeders;\n\nuse Illuminate\\Database\\Seeder;\nuse TCG\\Voyager\\Models\\Category;\nuse TCG\\Voyager\\Models\\DataType;\nuse TCG\\Voyager\\Models\\MenuItem;\nuse TCG\\Voyager\\Models\\Page;\nuse TCG\\Voyager\\Models\\Translation;\n\nclass TranslationsTableSeeder extends Seeder\n{\n    /**\n     * Auto generated seed file.\n     *\n     * @return void\n     */\n    public function run()\n    {\n        $this->dataTypesTranslations();\n        $this->categoriesTranslations();\n        $this->pagesTranslations();\n        $this->menusTranslations();\n    }\n\n    /**\n     * Auto generate Categories Translations.\n     *\n     * @return void\n     */\n    private function categoriesTranslations()\n    {\n        // Adding translations for 'categories'\n        //\n        $cat = Category::where('slug', 'category-1')->firstOrFail();\n        if ($cat->exists) {\n            $this->trans('pt', $this->arr(['categories', 'slug'], $cat->id), 'categoria-1');\n            $this->trans('pt', $this->arr(['categories', 'name'], $cat->id), 'Categoria 1');\n        }\n        $cat = Category::where('slug', 'category-2')->firstOrFail();\n        if ($cat->exists) {\n            $this->trans('pt', $this->arr(['categories', 'slug'], $cat->id), 'categoria-2');\n            $this->trans('pt', $this->arr(['categories', 'name'], $cat->id), 'Categoria 2');\n        }\n    }\n\n    /**\n     * Auto generate DataTypes Translations.\n     *\n     * @return void\n     */\n    private function dataTypesTranslations()\n    {\n        // Adding translations for 'display_name_singular'\n        //\n        $_fld = 'display_name_singular';\n        $_tpl = ['data_types', $_fld];\n        $dtp = DataType::where($_fld, __('voyager::seeders.data_types.post.singular'))->firstOrFail();\n        if ($dtp->exists) {\n            $this->trans('pt', $this->arr($_tpl, $dtp->id), 'Post');\n        }\n        $dtp = DataType::where($_fld, __('voyager::seeders.data_types.page.singular'))->firstOrFail();\n        if ($dtp->exists) {\n            $this->trans('pt', $this->arr($_tpl, $dtp->id), 'Página');\n        }\n        $dtp = DataType::where($_fld, __('voyager::seeders.data_types.user.singular'))->firstOrFail();\n        if ($dtp->exists) {\n            $this->trans('pt', $this->arr($_tpl, $dtp->id), 'Utilizador');\n        }\n        $dtp = DataType::where($_fld, __('voyager::seeders.data_types.category.singular'))->firstOrFail();\n        if ($dtp->exists) {\n            $this->trans('pt', $this->arr($_tpl, $dtp->id), 'Categoria');\n        }\n        $dtp = DataType::where($_fld, __('voyager::seeders.data_types.menu.singular'))->firstOrFail();\n        if ($dtp->exists) {\n            $this->trans('pt', $this->arr($_tpl, $dtp->id), 'Menu');\n        }\n        $dtp = DataType::where($_fld, __('voyager::seeders.data_types.role.singular'))->firstOrFail();\n        if ($dtp->exists) {\n            $this->trans('pt', $this->arr($_tpl, $dtp->id), 'Função');\n        }\n\n        // Adding translations for 'display_name_plural'\n        //\n        $_fld = 'display_name_plural';\n        $_tpl = ['data_types', $_fld];\n        $dtp = DataType::where($_fld, __('voyager::seeders.data_types.post.plural'))->firstOrFail();\n        if ($dtp->exists) {\n            $this->trans('pt', $this->arr($_tpl, $dtp->id), 'Posts');\n        }\n        $dtp = DataType::where($_fld, __('voyager::seeders.data_types.page.plural'))->firstOrFail();\n        if ($dtp->exists) {\n            $this->trans('pt', $this->arr($_tpl, $dtp->id), 'Páginas');\n        }\n        $dtp = DataType::where($_fld, __('voyager::seeders.data_types.user.plural'))->firstOrFail();\n        if ($dtp->exists) {\n            $this->trans('pt', $this->arr($_tpl, $dtp->id), 'Utilizadores');\n        }\n        $dtp = DataType::where($_fld, __('voyager::seeders.data_types.category.plural'))->firstOrFail();\n        if ($dtp->exists) {\n            $this->trans('pt', $this->arr($_tpl, $dtp->id), 'Categorias');\n        }\n        $dtp = DataType::where($_fld, __('voyager::seeders.data_types.menu.plural'))->firstOrFail();\n        if ($dtp->exists) {\n            $this->trans('pt', $this->arr($_tpl, $dtp->id), 'Menus');\n        }\n        $dtp = DataType::where($_fld, __('voyager::seeders.data_types.role.plural'))->firstOrFail();\n        if ($dtp->exists) {\n            $this->trans('pt', $this->arr($_tpl, $dtp->id), 'Funções');\n        }\n    }\n\n    /**\n     * Auto generate Pages Translations.\n     *\n     * @return void\n     */\n    private function pagesTranslations()\n    {\n        $page = Page::where('slug', 'hello-world')->firstOrFail();\n        if ($page->exists) {\n            $_arr = $this->arr(['pages', 'title'], $page->id);\n            $this->trans('pt', $_arr, 'Olá Mundo');\n            /**\n             * For configuring additional languages use it e.g.\n             *\n             * ```\n             *   $this->trans('es', $_arr, 'hola-mundo');\n             *   $this->trans('de', $_arr, 'hallo-welt');\n             * ```\n             */\n            $_arr = $this->arr(['pages', 'slug'], $page->id);\n            $this->trans('pt', $_arr, 'ola-mundo');\n\n            $_arr = $this->arr(['pages', 'body'], $page->id);\n            $this->trans('pt', $_arr, '<p>Olá Mundo. Scallywag grog swab Cat o\\'nine tails scuttle rigging hardtack cable nipper Yellow Jack. Handsomely spirits knave lad killick landlubber or just lubber deadlights chantey pinnace crack Jennys tea cup. Provost long clothes black spot Yellow Jack bilged on her anchor league lateen sail case shot lee tackle.</p>'\n                .\"\\r\\n\".'<p>Ballast spirits fluke topmast me quarterdeck schooner landlubber or just lubber gabion belaying pin. Pinnace stern galleon starboard warp carouser to go on account dance the hempen jig jolly boat measured fer yer chains. Man-of-war fire in the hole nipperkin handsomely doubloon barkadeer Brethren of the Coast gibbet driver squiffy.</p>');\n        }\n    }\n\n    /**\n     * Auto generate Menus Translations.\n     *\n     * @return void\n     */\n    private function menusTranslations()\n    {\n        $_tpl = ['menu_items', 'title'];\n        $_item = $this->findMenuItem(__('voyager::seeders.menu_items.dashboard'));\n        if ($_item->exists) {\n            $this->trans('pt', $this->arr($_tpl, $_item->id), 'Painel de Controle');\n        }\n\n        $_item = $this->findMenuItem(__('voyager::seeders.menu_items.media'));\n        if ($_item->exists) {\n            $this->trans('pt', $this->arr($_tpl, $_item->id), 'Media');\n        }\n\n        $_item = $this->findMenuItem(__('voyager::seeders.menu_items.posts'));\n        if ($_item->exists) {\n            $this->trans('pt', $this->arr($_tpl, $_item->id), 'Publicações');\n        }\n\n        $_item = $this->findMenuItem(__('voyager::seeders.menu_items.users'));\n        if ($_item->exists) {\n            $this->trans('pt', $this->arr($_tpl, $_item->id), 'Utilizadores');\n        }\n\n        $_item = $this->findMenuItem(__('voyager::seeders.menu_items.categories'));\n        if ($_item->exists) {\n            $this->trans('pt', $this->arr($_tpl, $_item->id), 'Categorias');\n        }\n\n        $_item = $this->findMenuItem(__('voyager::seeders.menu_items.pages'));\n        if ($_item->exists) {\n            $this->trans('pt', $this->arr($_tpl, $_item->id), 'Páginas');\n        }\n\n        $_item = $this->findMenuItem(__('voyager::seeders.menu_items.roles'));\n        if ($_item->exists) {\n            $this->trans('pt', $this->arr($_tpl, $_item->id), 'Funções');\n        }\n\n        $_item = $this->findMenuItem(__('voyager::seeders.menu_items.tools'));\n        if ($_item->exists) {\n            $this->trans('pt', $this->arr($_tpl, $_item->id), 'Ferramentas');\n        }\n\n        $_item = $this->findMenuItem(__('voyager::seeders.menu_items.menu_builder'));\n        if ($_item->exists) {\n            $this->trans('pt', $this->arr($_tpl, $_item->id), 'Menus');\n        }\n\n        $_item = $this->findMenuItem(__('voyager::seeders.menu_items.database'));\n        if ($_item->exists) {\n            $this->trans('pt', $this->arr($_tpl, $_item->id), 'Base de dados');\n        }\n\n        $_item = $this->findMenuItem(__('voyager::seeders.menu_items.settings'));\n        if ($_item->exists) {\n            $this->trans('pt', $this->arr($_tpl, $_item->id), 'Configurações');\n        }\n    }\n\n    private function findMenuItem($title)\n    {\n        return MenuItem::where('title', $title)->firstOrFail();\n    }\n\n    private function arr($par, $id)\n    {\n        return [\n            'table_name'  => $par[0],\n            'column_name' => $par[1],\n            'foreign_key' => $id,\n        ];\n    }\n\n    private function trans($lang, $keys, $value)\n    {\n        $_t = Translation::firstOrNew(array_merge($keys, [\n            'locale' => $lang,\n        ]));\n\n        if (!$_t->exists) {\n            $_t->fill(array_merge(\n                $keys,\n                ['value' => $value]\n            ))->save();\n        }\n    }\n}\n"
  },
  {
    "path": "database/seeders/UserSeeder.php",
    "content": "<?php\n\nnamespace Database\\Seeders;\n\nuse App\\Models\\User;\nuse Illuminate\\Database\\Seeder;\nuse Illuminate\\Support\\Facades\\Hash;\n\nclass UserSeeder extends Seeder\n{\n    /**\n     * Run the database seeders.\n     *\n     * @return void\n     */\n    public function run()\n    {\n        if (User::query()->count())\n        {\n            return;\n        }\n\n        $users = [\n            [\n                'name' => 'Misha Chekin',\n                'password' => Hash::make('1234'),\n                'email' => 'mchekin@gmail.com',\n            ],\n        ];\n\n        foreach ($users as $user) {\n            User::query()->create($user);\n        }\n    }\n}\n"
  },
  {
    "path": "database/seeders/VoyagerDatabaseSeeder.php",
    "content": "<?php\n\nnamespace Database\\Seeders;\n\nuse Illuminate\\Database\\Seeder;\nuse TCG\\Voyager\\Traits\\Seedable;\n\nclass VoyagerDatabaseSeeder extends Seeder\n{\n    use Seedable;\n\n    protected $seedersPath = __DIR__.'/';\n\n    /**\n     * Run the database seeders.\n     *\n     * @return void\n     */\n    public function run()\n    {\n        $this->seed(DataTypesTableSeeder::class);\n        $this->seed(DataRowsTableSeeder::class);\n        $this->seed(MenusTableSeeder::class);\n        $this->seed(MenuItemsTableSeeder::class);\n        $this->seed(RolesTableSeeder::class);\n        $this->seed(PermissionsTableSeeder::class);\n        $this->seed(PermissionRoleTableSeeder::class);\n        $this->seed(SettingsTableSeeder::class);\n    }\n}\n"
  },
  {
    "path": "database/seeders/VoyagerDummyDatabaseSeeder.php",
    "content": "<?php\n\nnamespace Database\\Seeders;\n\nuse Illuminate\\Database\\Seeder;\nuse TCG\\Voyager\\Traits\\Seedable;\n\nclass VoyagerDummyDatabaseSeeder extends Seeder\n{\n    use Seedable;\n\n    protected $seedersPath;\n\n    /**\n     * Run the database seeders.\n     *\n     * @return void\n     */\n    public function run()\n    {\n        $this->seedersPath = database_path('seeders').'/';\n        $this->seed('CategoriesTableSeeder');\n        $this->seed('UsersTableSeeder');\n        $this->seed('PostsTableSeeder');\n        $this->seed('PagesTableSeeder');\n        $this->seed('TranslationsTableSeeder');\n        $this->seed('PermissionRoleTableSeeder');\n    }\n}\n"
  },
  {
    "path": "docker/cron/Dockerfile",
    "content": "FROM php:7.4-cli\n\n# Install system dependencies\nRUN apt-get update && apt-get install -y \\\n    build-essential \\\n    git \\\n    curl \\\n    libpng-dev \\\n    libonig-dev \\\n    libxml2-dev \\\n    libzip-dev \\\n    zip \\\n    unzip \\\n    cron\n\n# Clear cache\nRUN apt-get clean && rm -rf /var/lib/apt/lists/*\n\n# Install PHP extensions\nRUN docker-php-ext-install pdo_mysql mbstring exif pcntl bcmath gd zip\n\n# Set working directory\nWORKDIR /var/www\n\n# Add crontab file in the cron directory\nADD ./docker/cron/scheduler /etc/cron.d/scheduler\n\n# Give execution rights on the cron job\nRUN chmod 0644 /etc/cron.d/scheduler\n\n# Apply the cron jobs\nRUN crontab /etc/cron.d/scheduler\n\n# run cron\nCMD [\"cron\", \"-f\"]"
  },
  {
    "path": "docker/cron/scheduler",
    "content": "* * * * * /usr/local/bin/php /var/www/artisan schedule:run > /proc/1/fd/1 2>/proc/1/fd/2\n"
  },
  {
    "path": "docker/mysql/my.cnf",
    "content": "[mysqld]\ngeneral_log = 1\ngeneral_log_file = /var/lib/mysql/general.log"
  },
  {
    "path": "docker/nginx/conf.d/app.conf",
    "content": "server {\n    listen 80;\n    index index.php index.html;\n    error_log  /var/log/nginx/error.log;\n    access_log /var/log/nginx/access.log;\n    root /var/www/public;\n    location ~ \\.php$ {\n        try_files $uri =404;\n        fastcgi_split_path_info ^(.+\\.php)(/.+)$;\n        fastcgi_pass app:9000;\n        fastcgi_index index.php;\n        include fastcgi_params;\n        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;\n        fastcgi_param PATH_INFO $fastcgi_path_info;\n    }\n    location / {\n        try_files $uri $uri/ /index.php?$query_string;\n        gzip_static on;\n    }\n}"
  },
  {
    "path": "docker/php/Dockerfile",
    "content": "FROM php:7.4-fpm\n\n# Arguments defined in docker-compose.yml\nARG user\nARG uid\n\n# Install NodeJS\nRUN curl -sL https://deb.nodesource.com/setup_12.x | bash\n\n# Install system dependencies\nRUN apt-get update && apt-get upgrade -y && apt-get install -y \\\n    build-essential \\\n    git \\\n    curl \\\n    libpng-dev \\\n    libonig-dev \\\n    libxml2-dev \\\n    libzip-dev \\\n    zip \\\n    unzip \\\n    nodejs \\\n    yarn\n\n# Clear cache\nRUN apt-get clean && rm -rf /var/lib/apt/lists/*\n\n# Install PHP extensions\nRUN docker-php-ext-install pdo_mysql mbstring exif pcntl bcmath gd zip\n\n# Install xdebug\nRUN pecl install xdebug && docker-php-ext-enable xdebug\n\n# Get latest Composer\nCOPY --from=composer:latest /usr/bin/composer /usr/bin/composer\n\n# Create system user to run Composer and Artisan Commands\nRUN useradd -G www-data,root -u $uid -d /home/$user $user\nRUN mkdir -p /home/$user/.composer && \\\n    chown -R $user:$user /home/$user\n\n# Set working directory\nWORKDIR /var/www\n\nUSER $user"
  },
  {
    "path": "docker/php/application-init.sh",
    "content": "composer install\n\nphp artisan key:generate\n\nphp artisan migrate --seed\n\nphp artisan storage:link\n\nphp-fpm"
  },
  {
    "path": "docker/php/local.ini",
    "content": "upload_max_filesize=40M\npost_max_size=40M\n\n[xdebug]\n\nxdebug.idekey=PHPSTORM\n\nxdebug.mode = debug\nxdebug.client_host=host.docker.internal\nxdebug.client_port=9001\n\nxdebug.log=/var/www/storage/logs/xdebug.log"
  },
  {
    "path": "docker-compose.yml",
    "content": "version: \"3.7\"\nservices:\n\n  #PHP Service\n  app:\n    build:\n      args:\n        user: user\n        uid: 1000\n      context: ./\n      dockerfile: docker/php/Dockerfile\n    image: rpg\n    container_name: rpg-app\n    restart: unless-stopped\n    tty: true\n    environment:\n      SERVICE_NAME: app\n      SERVICE_TAGS: dev\n      PHP_IDE_CONFIG: serverName=RpgServer\n    working_dir: /var/www\n    command: /var/www/docker/php/application-init.sh\n    volumes:\n      - ./:/var/www\n      - ./docker/php/local.ini:/usr/local/etc/php/conf.d/local.ini\n    networks:\n      - rpg-app-network\n    depends_on:\n      - db\n\n  #Cron tab service\n  cron:\n    build:\n      context: .\n      dockerfile: docker/cron/Dockerfile\n    image: cron\n    container_name: rpg-cron\n    restart: unless-stopped\n    tty: true\n    environment:\n      SERVICE_NAME: app\n      SERVICE_TAGS: dev\n    working_dir: /var/www\n    volumes:\n      - ./:/var/www\n    networks:\n      - rpg-app-network\n    depends_on:\n      - app\n\n  #Nginx Service\n  nginx:\n    image: nginx:1.17-alpine\n    container_name: rpg-nginx\n    restart: unless-stopped\n    tty: true\n    ports:\n      - \"8080:80\"\n      - \"443:443\"\n    volumes:\n      - ./:/var/www\n      - ./docker/nginx/conf.d/:/etc/nginx/conf.d/\n    networks:\n      - rpg-app-network\n    depends_on:\n      - app\n\n  #MySQL Service\n  db:\n    image: mysql:5.7.32\n    container_name: rpg-db\n    restart: unless-stopped\n    tty: true\n    ports:\n      - \"3306:3306\"\n    environment:\n      MYSQL_DATABASE: ${DB_DATABASE}\n      MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}\n      MYSQL_PASSWORD: ${DB_PASSWORD}\n      MYSQL_USER: ${DB_USERNAME}\n      SERVICE_TAGS: dev\n      SERVICE_NAME: mysql\n    volumes:\n      - dbdata:/var/lib/mysql\n      - ./docker/mysql/my.cnf:/etc/mysql/my.cnf\n    networks:\n      - rpg-app-network\n\n#Docker Networks\nnetworks:\n  rpg-app-network:\n    driver: bridge\n\n#Volumes\nvolumes:\n  dbdata:\n    driver: local\n"
  },
  {
    "path": "docs/docker_environment.md",
    "content": "## Docker Development Environment\n\n![](https://raw.githubusercontent.com/mchekin/rpg/f19c452aefcbd028c7db521bd50d1cec5995b137/public/images/locations/Fortress-300px.png)\n\n### Table of Contents\n\n1. [Requirements](#requirments)\n2. [Installation](#installation)\n4. [Using Admin Dashboard](#usingadmindashboard)\n\n<a name=\"requirements\"></a>\n### Requirements\n- [Docker & Docker Compose](https://www.docker.com/get-started)\n\n<a name=\"installation\"></a>\n### Installation\n- Clone the repo\n\n        git clone https://github.com/mchekin/rpg.git game\n\n- Navigate to the project folder\n\n        cd game\n        \n- Create .env file from the .env.example file\n\n        cp .env.docker.example .env\n  \n  On Windows:\n\n        copy .env.docker.example .env\n\n- Bring the containers up\n\n        docker-compose up -d\n\n- Install NPM packages\n\n        docker-compose exec app npm install\n\n- Build frontend assets\n\n        docker-compose exec app npm run dev\n\n- Navigate to [http://localhost:8080/](http://localhost/8080)\n\n<a name=\"usingadmindashboard\"></a>\n### Using Admin Dashboard\n[Voyager](https://laravelvoyager.com/) has been integrated into the project as an Admin Dashboard.\n\nTo use the Admin:\n\n- Register a user in the application (You can skip this step if you already have a user).\n- Give the user the admin role by running:\n\n        docker-compose exec app php artisan voyager:admin <user email>\n        \n- Navigate to [http://localhost:8080/admin](http://localhost:8080/admin).\n- Log in with the user credentials (If not logged in automatically).\n\nFurther information about using Voyager can be found on its [official website](https://laravelvoyager.com/).\n"
  },
  {
    "path": "docs/local_environment.md",
    "content": "## Local Development Environment\n\n![](https://raw.githubusercontent.com/mchekin/rpg/f19c452aefcbd028c7db521bd50d1cec5995b137/public/images/locations/Townhall-300px.png)\n\n### Table of Contents\n\n1. [Requirements](#requirments)\n2. [Installation](#installation)\n3. [Using Admin Dashboard](#usingadmindashboard)\n\n<a name=\"requirements\"></a>\n### Requirements (for local development)\n\n- PHP 7.2.0 or Higher\n- [Git](https://git-scm.com/)\n- [Composer](https://getcomposer.org/)\n- [SQLite](https://www.sqlite.org/)\n- [NodeJS](https://nodejs.org/)\n\n<a name=\"installation\"></a>\n### Installation\n- Clone the repo\n\n        git clone https://github.com/mchekin/rpg.git game\n\n- Navigate to the project folder\n\n        cd game\n\n- Create .env file from the .env.example file\n\n        cp .env.example .env\n  \n  On Windows:\n  \n        copy .env.example .env\n\n- Run composer install to import the dependencies and enable auto-loading\n\n        composer install\n\n- Generate Laravel Application key\n\n        php artisan key:generate\n\n- Create SQLite database file\n\n        touch database/database.sqlite\n  \n  On Windows:\n  \n        copy NUL database\\database.sqlite\n\n- Run Laravel database migrations and seeds\n\n        php artisan migrate --seed\n\n- Compile frontend assets \n\n        npm install & npm run dev\n\n- Create a symbolic link from \"public/storage\" to \"storage/app/public\"\n\n        php artisan storage:link  \n\n- Run PHP build-in development server on the host machine\n\n        php artisan serve  \n\n- Navigate to [http://localhost:8000/](http://localhost:8000/)\n\n- Enable Laravel Task Scheduling\n\n    1. Open the cron tab file\n    \n            crontab -e\n            \n    2. Add the following line and save\n            \n            * * * * * php <path-to-project>/artisan schedule:run >> /dev/null 2>&1\n  \n  On Windows:\n  \n  Open the Terminal as Administrator, navigate to the project's root folder and run:\n    \n        schtasks /create /sc minute /mo 1 /tn \"RPG SCHEDULER\" /tr %cd%\\scheduler.bat\n        \n    To disable the annoying command-line pop-up each time the task runs:\n    \n    1. Open Windows \"Run\" dialog by pressing \"Windows Key + r\"\n    2. Enter type \"Taskschd.msc\" and press Enter. This will open the \"Task Scheduler\".\n    3. In Task Scheduler's \"Active Tasks\" section find the \"RPG SCHEDULER\" task and double-click it.\n    4. In the left \"Actions\" panel click \"Properties\". This will open \"Properties\" pop-up.\n    5. In the pop-up select the \"Run whether user is logged in or not\" and press Enter.\n    You maybe asked for your Windows user's password to complete the process.\n        \n  To remove the scheduled task you can use\n  \n        schtasks /delete /tn \"RPG SCHEDULER\" /f\n\n<a name=\"usingadmindashboard\"></a>\n### Using Admin Dashboard\n[Voyager](https://laravelvoyager.com/) has been integrated into the project as an Admin Dashboard.\n\nTo use the Admin:\n\n- Register a user in the application (You can skip this step if you already have a user).\n- Give the user the admin role by running:\n\n        php artisan voyager:admin <user email>\n        \n- Navigate to [http://localhost:8000/admin](http://localhost:8000/admin).\n- Log in with the user credentials (If not logged in automatically).\n\nFurther information about using Voyager can be found on its [official website](https://laravelvoyager.com/)."
  },
  {
    "path": "hooks/hooks.json",
    "content": "{}"
  },
  {
    "path": "package.json",
    "content": "{\n    \"private\": true,\n    \"scripts\": {\n        \"dev\": \"npm run development\",\n        \"development\": \"mix\",\n        \"watch\": \"mix watch\",\n        \"watch-poll\": \"mix watch -- --watch-options-poll=1000\",\n        \"hot\": \"mix watch --hot\",\n        \"prod\": \"npm run production\",\n        \"production\": \"mix --production\"\n    },\n    \"devDependencies\": {\n        \"@fortawesome/fontawesome-free\": \"^5.15.1\",\n        \"axios\": \"^0.21\",\n        \"bootstrap\": \"^4.0.0\",\n        \"jquery\": \"^3.2\",\n        \"laravel-mix\": \"^6.0.6\",\n        \"lodash\": \"^4.17.21\",\n        \"popper.js\": \"^1.12\",\n        \"postcss\": \"^8.1.14\",\n        \"resolve-url-loader\": \"^2.3.1\",\n        \"sass\": \"^1.20.1\",\n        \"sass-loader\": \"^8.0.0\",\n        \"vue\": \"^2.5.17\",\n        \"vue-loader\": \"^15.9.6\",\n        \"vue-template-compiler\": \"^2.6.10\"\n    }\n}\n"
  },
  {
    "path": "phpunit.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<phpunit xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:noNamespaceSchemaLocation=\"./vendor/phpunit/phpunit/phpunit.xsd\"\n         backupGlobals=\"false\"\n         backupStaticAttributes=\"false\"\n         bootstrap=\"vendor/autoload.php\"\n         colors=\"true\"\n         convertErrorsToExceptions=\"true\"\n         convertNoticesToExceptions=\"true\"\n         convertWarningsToExceptions=\"true\"\n         processIsolation=\"false\"\n         stopOnFailure=\"false\">\n    <testsuites>\n        <testsuite name=\"Unit\">\n            <directory suffix=\"Test.php\">./tests/Unit</directory>\n        </testsuite>\n        <testsuite name=\"Feature\">\n            <directory suffix=\"Test.php\">./tests/Feature</directory>\n        </testsuite>\n    </testsuites>\n    <coverage processUncoveredFiles=\"true\">\n        <include>\n            <directory suffix=\".php\">./app</directory>\n        </include>\n    </coverage>\n    <php>\n        <server name=\"APP_ENV\" value=\"testing\"/>\n        <server name=\"BCRYPT_ROUNDS\" value=\"4\"/>\n        <server name=\"CACHE_DRIVER\" value=\"array\"/>\n        <server name=\"DB_CONNECTION\" value=\"sqlite\"/>\n        <server name=\"DB_DATABASE\" value=\":memory:\"/>\n        <server name=\"MAIL_MAILER\" value=\"array\"/>\n        <server name=\"QUEUE_CONNECTION\" value=\"sync\"/>\n        <server name=\"SESSION_DRIVER\" value=\"array\"/>\n        <server name=\"TELESCOPE_ENABLED\" value=\"false\"/>\n    </php>\n</phpunit>\n"
  },
  {
    "path": "public/.htaccess",
    "content": "<IfModule mod_rewrite.c>\n    <IfModule mod_negotiation.c>\n        Options -MultiViews -Indexes\n    </IfModule>\n\n    RewriteEngine On\n\n    # Handle Authorization Header\n    RewriteCond %{HTTP:Authorization} .\n    RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]\n\n    # Redirect Trailing Slashes If Not A Folder...\n    RewriteCond %{REQUEST_FILENAME} !-d\n    RewriteCond %{REQUEST_URI} (.+)/$\n    RewriteRule ^ %1 [L,R=301]\n\n    # Send Requests To Front Controller...\n    RewriteCond %{REQUEST_FILENAME} !-d\n    RewriteCond %{REQUEST_FILENAME} !-f\n    RewriteRule ^ index.php [L]\n</IfModule>"
  },
  {
    "path": "public/index.php",
    "content": "<?php\n\nuse Illuminate\\Contracts\\Http\\Kernel;\nuse Illuminate\\Http\\Request;\n\ndefine('LARAVEL_START', microtime(true));\n\n/*\n|--------------------------------------------------------------------------\n| Check If The Application Is Under Maintenance\n|--------------------------------------------------------------------------\n|\n| If the application is in maintenance / demo mode via the \"down\" command\n| we will load this file so that any pre-rendered content can be shown\n| instead of starting the framework, which could cause an exception.\n|\n*/\n\nif (file_exists(__DIR__.'/../storage/framework/maintenance.php')) {\n    require __DIR__.'/../storage/framework/maintenance.php';\n}\n\n/*\n|--------------------------------------------------------------------------\n| Register The Auto Loader\n|--------------------------------------------------------------------------\n|\n| Composer provides a convenient, automatically generated class loader for\n| this application. We just need to utilize it! We'll simply require it\n| into the script here so we don't need to manually load our classes.\n|\n*/\n\nrequire __DIR__.'/../vendor/autoload.php';\n\n/*\n|--------------------------------------------------------------------------\n| Run The Application\n|--------------------------------------------------------------------------\n|\n| Once we have the application, we can handle the incoming request using\n| the application's HTTP kernel. Then, we will send the response back\n| to this client's browser, allowing them to enjoy our application.\n|\n*/\n\n$app = require_once __DIR__.'/../bootstrap/app.php';\n\n$kernel = $app->make(Kernel::class);\n\n$response = tap($kernel->handle(\n    $request = Request::capture()\n))->send();\n\n$kernel->terminate($request, $response);"
  },
  {
    "path": "public/js/character-create.js",
    "content": "(function($) {\n    var carouselRace = $(\".carousel-race\");\n    var carouselGender = $(\".carousel-gender\");\n\n    var carouselRaceControl = $('#race-carousel');\n    var carouselGenderControl = $('#gender-carousel');\n\n    // Enable Carousel Controls\n    function changeRace() {\n        var raceIdRegex = /^(?:\\w+)-(?:\\w+)-([0-9]+)$/;\n        var raceIdString = $('.carousel-item.active', carouselRaceControl).attr('id');\n        var matches = raceIdRegex.exec(raceIdString);\n        $('#race_id').val(matches[1]);\n    }\n\n    function changeGender() {\n        var gender = $('.carousel-item.active', carouselGenderControl).attr('id');\n        $('.img-race',carouselRace).hide();\n        $('.img-'+gender, carouselRace).show();\n        $('#gender').val(gender);\n    };\n\n    $(\".left-race\").click(function () {\n        carouselRace.carousel(\"prev\");\n        changeRace();\n    });\n    $(\".right-race\").click(function () {\n        carouselRace.carousel(\"next\");\n        changeRace();\n    });\n\n    $(\".left-gender\").click(function () {\n        carouselGender.carousel(\"prev\");\n        changeGender();\n    });\n    $(\".right-gender\").click(function () {\n        carouselGender.carousel(\"next\");\n        changeGender();\n    });\n})(jQuery );\n"
  },
  {
    "path": "public/js/character-update.js",
    "content": "(function ($) {\n\n    $(\".increment_attribute\").click(function (event) {\n\n        let attributeName = this.id;\n\n        $('#attribute_input').val(attributeName);\n    });\n\n})(jQuery);\n"
  },
  {
    "path": "public/js/vcountdown.js",
    "content": "/*jslint browser: true*/\n/*global define, module, exports*/\n(function (root, factory) {\n    \"use strict\";\n    if (typeof define === 'function' && define.amd) {\n        define([], factory);\n    } else if (typeof exports === 'object') {\n        module.exports = factory();\n    } else {\n        root.VCountdown = factory();\n    }\n}(this, function () {\n    \"use strict\";\n\n    let VCountdown = function (options) {\n        if (!this || !(this instanceof VCountdown)) {\n            return new VCountdown(options);\n        }\n\n        if (!options) {\n            options = {};\n        }\n\n        if (!options.target) {\n            throw 'Provide a target to count characters';\n        }\n\n        this.target   = document.querySelector(options.target);\n        this.maxChars = options.maxChars || 140;\n\n        this.countdown();\n    };\n\n    VCountdown.prototype = {\n\n        hasClass: function (el, name) {\n            return new RegExp('(\\\\s|^)' + name + '(\\\\s|$)').test(el.className);\n        },\n\n        addClass: function (el, name) {\n            if (!this.hasClass(el, name)) {\n                el.className += (el.className ? ' ' : '') + name;\n            }\n        },\n\n        removeClass: function (el, name) {\n            if (this.hasClass(el, name)) {\n                el.className = el.className.replace(new RegExp('(\\\\s|^)' + name + '(\\\\s|$)'), ' ').replace(/^\\s+|\\s+$/g, '');\n            }\n        },\n\n        createEls: function (name, props) {\n            let el = document.createElement(name), p;\n            for (p in props) {\n                if (props.hasOwnProperty(p)) {\n                    el[p] = props[p];\n                }\n            }\n            return el;\n        },\n\n        insertAfter: function (referenceNode, newNode) {\n            referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);\n        },\n\n        update: function () {\n            let target = this.target,\n                currentCount = target.value.length,\n                remaining    = this.maxChars - currentCount;\n\n            if (remaining > 10) {\n                this.removeClass(target.nextElementSibling, 'warn');\n            } else {\n                this.addClass(target.nextElementSibling, 'warn');\n            }\n\n            target.nextElementSibling.innerHTML = remaining + ' remaining';\n        },\n        setMaxChars: function () {\n            this.target.setAttribute('maxlength', this.maxChars);\n        },\n\n        charsLen: function () {\n            let element = this.createEls('div', {className: 'chars-length'});\n            element.innerHTML = this.maxChars;\n\n            this.insertAfter(this.target, element);\n\n            this.update();\n        },\n\n        countdown: function () {\n            this.setMaxChars();\n            this.charsLen();\n\n            this.target.addEventListener('keyup', this.update.bind(this), false);\n        }\n    };\n\n    return VCountdown;\n}));\n"
  },
  {
    "path": "public/robots.txt",
    "content": "User-agent: *\nDisallow:\n"
  },
  {
    "path": "public/web.config",
    "content": "<!--\n    Rewrites requires Microsoft URL Rewrite Module for IIS\n    Download: https://www.iis.net/downloads/microsoft/url-rewrite\n    Debug Help: https://docs.microsoft.com/en-us/iis/extensions/url-rewrite-module/using-failed-request-tracing-to-trace-rewrite-rules\n-->\n<configuration>\n  <system.webServer>\n    <rewrite>\n      <rules>\n        <rule name=\"Imported Rule 1\" stopProcessing=\"true\">\n          <match url=\"^(.*)/$\" ignoreCase=\"false\" />\n          <conditions>\n            <add input=\"{REQUEST_FILENAME}\" matchType=\"IsDirectory\" ignoreCase=\"false\" negate=\"true\" />\n          </conditions>\n          <action type=\"Redirect\" redirectType=\"Permanent\" url=\"/{R:1}\" />\n        </rule>\n        <rule name=\"Imported Rule 2\" stopProcessing=\"true\">\n          <match url=\"^\" ignoreCase=\"false\" />\n          <conditions>\n            <add input=\"{REQUEST_FILENAME}\" matchType=\"IsDirectory\" ignoreCase=\"false\" negate=\"true\" />\n            <add input=\"{REQUEST_FILENAME}\" matchType=\"IsFile\" ignoreCase=\"false\" negate=\"true\" />\n          </conditions>\n          <action type=\"Rewrite\" url=\"index.php\" />\n        </rule>\n      </rules>\n    </rewrite>\n  </system.webServer>\n</configuration>\n"
  },
  {
    "path": "readme.md",
    "content": "## Online Role Playing Game\n\n![](https://raw.githubusercontent.com/mchekin/rpg/f19c452aefcbd028c7db521bd50d1cec5995b137/public/images/locations/Blacksmith-300px.png)\n\n![](https://travis-ci.org/mchekin/rpg.svg)\n\n### Table of Contents\n1. [Running in development environment](#runningindevelopmentenvironment)\n2. [License](#license)\n\n<a name=\"runningindevelopmentenvironment\"></a>\n### Running in development environment\n\n#### Docker (recommended)\n\nGo to >>> [Guide](docs/docker_environment.md)\n\n#### Local\n\nGo to >>> [Guide](docs/local_environment.md)\n\n<a name=\"license\"></a>\n### License\nOpen-sourced software licensed under the [MIT license](http://opensource.org/licenses/MIT)\n"
  },
  {
    "path": "resources/js/app.js",
    "content": "\n\nrequire('./bootstrap');\n\nwindow.Vue = require('vue').default;\n\nVue.filter('underscoreToWhitespace', function (value) {\n    return value.split('_').join(' ');\n});\n\nVue.filter('capitalize', function (value) {\n    return value.charAt(0).toUpperCase() + value.slice(1)\n});\n\nVue.filter('plusForPositiveNumber', function (value) {\n    return (Number.isInteger(value) && value > 0)\n        ? '+' + value\n        : value;\n});\n\nVue.component(\n    'popup-modal',\n    require('./components/PopupModal.vue').default\n);\n\nVue.component(\n    'inventory-management',\n    require('./components/InventoryManagement.vue').default\n);\n\nVue.component(\n    'store-management',\n    require('./components/StoreManagement.vue').default\n);\n\nVue.component(\n    'store-trade',\n    require('./components/StoreTrade.vue').default\n);\n\nVue.component(\n    'flash-messages',\n    require('./components/FlashMessages.vue').default\n);\n\n\nconst app = new Vue({\n    el: '#app',\n});\n"
  },
  {
    "path": "resources/js/bootstrap.js",
    "content": "window._ = require('lodash');\n\n/**\n * We'll load jQuery and the Bootstrap jQuery plugin which provides support\n * for JavaScript based Bootstrap features such as modals and tabs. This\n * code may be modified to fit the specific needs of your application.\n */\n\ntry {\n    window.Popper = require('popper.js').default;\n    window.$ = window.jQuery = require('jquery');\n\n    require('bootstrap');\n} catch (e) {}\n\n/**\n * We'll load the axios HTTP library which allows us to easily issue requests\n * to our Laravel back-end. This library automatically handles sending the\n * CSRF token as a header based on the value of the \"XSRF\" token cookie.\n */\n\nwindow.axios = require('axios');\n\nwindow.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';\n\n/**\n * Next we will register the CSRF Token as a common header with Axios so that\n * all outgoing HTTP requests automatically have it attached. This is just\n * a simple convenience so we don't have to attach every token manually.\n */\n\nlet token = document.head.querySelector('meta[name=\"csrf-token\"]');\n\nif (token) {\n    window.axios.defaults.headers.common['X-CSRF-TOKEN'] = token.content;\n} else {\n    console.error('CSRF token not found: https://laravel.com/docs/csrf#csrf-x-csrf-token');\n}\n\n/**\n * Echo exposes an expressive API for subscribing to channels and listening\n * for events that are broadcast by Laravel. Echo and event broadcasting\n * allows your team to easily build robust real-time web applications.\n */\n\n// import Echo from 'laravel-echo';\n\n// window.Pusher = require('pusher-js');\n\n// window.Echo = new Echo({\n//     broadcaster: 'pusher',\n//     key: process.env.MIX_PUSHER_APP_KEY,\n//     cluster: process.env.MIX_PUSHER_APP_CLUSTER,\n//     forceTLS: true\n// });\n"
  },
  {
    "path": "resources/js/components/FlashMessages.vue",
    "content": "<template>\n  <Transition name=\"slide-fade\">\n    <div v-if=\"messages.length\" class=\"\" role=\"alert\">\n      <ul class=\"list-unstyled\">\n        <li v-for=\"(message, index) in messages\" :key=\"index\" :class=\"{\n          'alert alert-danger': message.type === 'error',\n          'alert alert-success': message.type === 'success'\n        }\">\n          {{ message.text }}\n          <button type=\"button\" class=\"dismiss-message\" aria-label=\"Close\" v-on:click=\"removeMessage(index)\">\n            <span aria-hidden=\"true\">&times;</span>\n          </button>\n        </li>\n      </ul>\n    </div>\n  </Transition>\n</template>\n\n<script>\nexport default {\n  mounted() {\n    this.$root.$on('errorHappened', error => {\n      this.addMessage({\n          'text': error,\n          'type': 'error',\n      });\n    });\n\n    this.$root.$on('successHappened', status => {\n      this.addMessage({\n        'text': status,\n        'type': 'success',\n      });\n    });\n  },\n\n  data() {\n    return {\n      messages: [],\n      timers: [],\n    };\n  },\n\n  created() {\n    this.$attrs.messages.forEach(message => {\n        this.addMessage(message);\n    });\n  },\n\n  methods: {\n\n    addMessage(message) {\n      this.messages.push(message);\n\n      let timeout = message.type === 'success' ? 2000: 10000;\n\n      this.timers.push(setTimeout(() => {\n        this.removeMessage(0)\n      }, timeout));\n    },\n\n    removeMessage(index) {\n\n      this.messages.splice(index, 1);\n      this.timers.splice(index, 1);\n    },\n  }\n}\n</script>\n<style scoped>\n.slide-fade-enter-active,\n.slide-fade-leave-active {\n  transition: all 0.4s;\n}\n\n.slide-fade-enter,\n.slide-fade-leave-to {\n  transform: translateX(400px);\n  opacity: 0;\n}\n.dismiss-message {\n  position: absolute;\n  top: 0;\n  right: 0;\n  z-index: 2;\n  padding: 0.75rem 1.25rem;\n  color: inherit;\n  background-color: transparent;\n  border: 0;\n  float: right;\n  font-size: 1.35rem;\n  font-weight: 700;\n  line-height: 1;\n  text-shadow: 0 1px 0 #fff;\n  opacity: 0.5;\n}\n</style>\n"
  },
  {
    "path": "resources/js/components/InventoryManagement.vue",
    "content": "<template>\n    <div>\n\n        <div class=\"row\">\n            <popup-modal v-if=\"showModal\" @closeModal=\"showModal = false\">\n\n                <div slot=\"body\">\n\n                    <div class=\"font-weight-bold\">\n                        {{ itemToDisplay.name }}\n\n                        <button type=\"submit\"\n                                class=\"close\"\n                                @click.stop.prevent=\"showModal = false\">\n                            x\n                        </button>\n                    </div>\n\n                    <div class=\"modal-item-price-image\">\n                        <img :src=\"'/' + itemToDisplay.image_file_path\" :alt=\"itemToDisplay.name\">\n                    </div>\n\n                    <table class=\"table model-item-attributes-table\">\n                        <caption class=\"caption-top\">Attributes</caption>\n                        <tr>\n                            <th scope=\"row\">Sell price</th>\n                            <td>\n                                <form>\n                                    <label for=\"set-item-price\"></label>\n                                    <input type=\"number\"\n                                           name=\"money_amount\"\n                                           id=\"set-item-price\"\n                                           class=\"w-100\"\n                                           v-model.number=\"itemToDisplay.price\"\n                                           @change.stop.prevent=\"changeItemPrice(itemToDisplay)\"\n                                           min=\"0\"\n                                           aria-label=\"Set item price\">\n                                </form>\n                            </td>\n                        </tr>\n                        <tr>\n                            <th scope=\"row\">Type</th>\n                            <td>{{ itemToDisplay.type | underscoreToWhitespace | capitalize }}</td>\n                        </tr>\n                        <tr>\n                            <th scope=\"row\">Effects</th>\n                            <td>\n                                <ul class=\"list-unstyled modal-item-effects\">\n                                    <li v-for=\"effect in itemToDisplay.effects\" class=\"\" :key=\"effect.type\">\n                                        {{ effect.type | capitalize }}: {{ effect.quantity | plusForPositiveNumber }}\n                                    </li>\n                                </ul>\n                            </td>\n                        </tr>\n                    </table>\n                </div>\n\n            </popup-modal>\n        </div>\n\n        <div class=\"mx-1\">\n            <div class=\"row mx-1 table-dark align-items-center\"\n                 @drop=\"onDrop($event, 'equipment')\"\n                 @dragover.prevent\n                 @dragenter.prevent>\n                <div class=\"col-3 equipment-item\">\n                    {{ 'head_gear' | underscoreToWhitespace | capitalize }}\n                    <button type=\"submit\"\n                            @click.stop.prevent=\"openItemModal(getEquipmentItem('head_gear'), 'equipment')\"\n                            @dragstart=\"startDrag($event, parseInt(getEquipmentItem('head_gear').pivot.inventory_slot_number), 'equipment')\"\n                            draggable=\"true\"\n                            class=\"btn btn-link-thin\"\n                            v-if=\"getEquipmentItem('head_gear')\">\n                        <img :src=\"asset(getEquipmentItem('head_gear').image_file_path)\"\n                             :alt=\"getEquipmentItem('head_gear').name\">\n                    </button>\n                </div>\n                <div class=\"col-3 equipment-item\">\n                    {{ 'body_armor' | underscoreToWhitespace | capitalize }}\n                    <button type=\"submit\"\n                            @click.stop.prevent=\"openItemModal(getEquipmentItem('body_armor'), 'equipment')\"\n                            @dragstart=\"startDrag($event, parseInt(getEquipmentItem('body_armor').pivot.inventory_slot_number), 'equipment')\"\n                            draggable=\"true\"\n                            class=\"btn btn-link-thin\"\n                            v-if=\"getEquipmentItem('body_armor')\">\n                        <img :src=\"asset(getEquipmentItem('body_armor').image_file_path)\"\n                             :alt=\"getEquipmentItem('body_armor').name\">\n                    </button>\n                </div>\n                <div class=\"col-3 equipment-item\">\n                    {{ 'main_hand' | underscoreToWhitespace | capitalize }}\n                    <button type=\"submit\"\n                            @click.stop.prevent=\"openItemModal(getEquipmentItem('main_hand'), 'equipment')\"\n                            @dragstart=\"startDrag($event, parseInt(getEquipmentItem('main_hand').pivot.inventory_slot_number), 'equipment')\"\n                            draggable=\"true\"\n                            class=\"btn btn-link-thin\"\n                            v-if=\"getEquipmentItem('main_hand')\">\n                        <img :src=\"asset(getEquipmentItem('main_hand').image_file_path)\"\n                             :alt=\"getEquipmentItem('main_hand').name\">\n                    </button>\n                </div>\n                <div class=\"col-3 equipment-item\">\n                    {{ 'off_hand' | underscoreToWhitespace | capitalize }}\n                    <button type=\"submit\"\n                            @click.stop.prevent=\"openItemModal(getEquipmentItem('off_hand'), 'equipment')\"\n                            @dragstart=\"startDrag($event, parseInt(getEquipmentItem('off_hand').pivot.inventory_slot_number), 'equipment')\"\n                            draggable=\"true\"\n                            class=\"btn btn-link-thin\"\n                            v-if=\"getEquipmentItem('off_hand')\">\n                        <img :src=\"asset(getEquipmentItem('off_hand').image_file_path)\"\n                             :alt=\"getEquipmentItem('off_hand').name\">\n                    </button>\n                </div>\n            </div>\n        </div>\n\n        <div>\n            <div class=\"my-3 row mx-1 table-dark align-items-center\">\n\n                <div v-for=\"index in total_inventory_slots\" :key=\"index\"\n                     :id=\"index-1\"\n                     :class=\"[isEquipped(index-1) ? 'inventory-item equipped' : 'inventory-item']\"\n                     @drop=\"onDrop($event, 'inventory')\"\n                     @dragover.prevent\n                     @dragenter.prevent>\n                    <button type=\"submit\"\n                            @click.stop.prevent=\"openItemModal(getInventoryItem(index-1), 'inventory')\"\n                            @dragstart=\"startDrag($event, index-1, 'inventory')\"\n                            draggable=\"true\"\n                            class=\"btn btn-link-thin\"\n                            v-if=\"getInventoryItem(index-1)\">\n                        <img :src=\"asset(getInventoryItem(index-1).image_file_path)\"\n                             :alt=\"getInventoryItem(index-1).name\">\n                    </button>\n                </div>\n\n            </div>\n\n        </div>\n\n    </div>\n</template>\n\n<script>\n\nexport default {\n    mounted() {\n\n    },\n\n    data() {\n        return {\n            itemToDisplay: {\n                pivot: {\n                    inventory_slot_number: null,\n                    status: ''\n                },\n                image_file_path: '',\n                price: 0,\n                type: '',\n                name: '',\n                effects: {\n                    quantity: 0,\n                    type: ''\n                }\n            },\n            showModal: false,\n            showContainer: 'inventory',\n            sourceContainer: 'inventory',\n            money_to_store: 0,\n            money_to_inventory: 0,\n            total_inventory_slots: 25,\n            total_store_slots: 25,\n            character: {\n                name: '',\n                inventory: {\n                    items: [\n                        {\n                            pivot: {\n                                inventory_slot_number: null,\n                                status: ''\n                            },\n                            image_file_path: '',\n                            price: 0,\n                            type: '',\n                            name: '',\n                            effects: {\n                                quantity: 0,\n                                type: ''\n                            }\n                        }\n                    ],\n                    money: 0\n                }\n            }\n        }\n    },\n\n    created() {\n        this.character = this.$attrs.character;\n    },\n\n    methods: {\n        equipItem(item) {\n\n            if (!item) {\n                return;\n            }\n\n            item.pivot.status = 'equipped';\n\n            axios.post('/api/inventory/item/' + item.id + '/equip')\n                .then(() => {\n                    this.logSuccess('Equipped: ' + item.name);\n                }).catch(error => {\n                this.logError('Equipping item failed: ' + error.response.data.message);\n            });\n        },\n\n        unEquipItem(item) {\n\n            if (!item) {\n                return;\n            }\n\n            item.pivot.status = 'in_backpack';\n\n            axios.post('/api/inventory/item/' + item.id + '/un-equip')\n                .then(() => {\n                    this.logSuccess('Un-equipped: ' + item.name);\n                }).catch(error => {\n                this.logError('Un-equipping item failed: ' + error.response.data.message);\n            });\n        },\n\n        findFreeStoreSlot() {\n\n            for (let slot = 0; slot < this.total_store_slots; slot++) {\n\n                if (this.getStoreItem(slot) === undefined) {\n                    return slot;\n                }\n            }\n\n            return null;\n        },\n\n        findFreeInventorySlot() {\n\n            for (let slot = 0; slot < this.total_inventory_slots; slot++) {\n\n                if (this.getInventoryItem(slot) === undefined) {\n                    return slot;\n                }\n            }\n\n            return null;\n        },\n\n        moveItemToStore(item) {\n\n            if (!item) {\n                return;\n            }\n\n            this.showModal = false;\n\n            item.pivot.inventory_slot_number = this.findFreeStoreSlot();\n            item.pivot.status = 'in_backpack';\n\n            this.character.store.items.push(item);\n\n            let index = this.character.inventory.items.indexOf(item);\n\n            if (index > -1) {\n                this.character.inventory.items.splice(index, 1);\n            }\n\n            axios.post('/api/inventory/item/' + item.id + '/move-to-store')\n                .then(() => {\n                    this.logSuccess('Moved: ' + item.name + ' to the store');\n\n                    this.money_to_store = 0;\n                }).catch(error => {\n                this.logError('Moving item to the store failed: ' + error.response.data.message);\n            });\n        },\n\n        moveItemToInventory(item) {\n\n            if (!item) {\n                return;\n            }\n\n            item.pivot.inventory_slot_number = this.findFreeInventorySlot();\n\n            this.character.inventory.items.push(item);\n\n            let index = this.character.store.items.indexOf(item);\n\n            if (index > -1) {\n                this.character.store.items.splice(index, 1);\n            }\n\n            axios.post('/api/store/item/' + item.id + '/move-to-inventory')\n                .then(() => {\n                    this.logSuccess('Moved: ' + item.name + ' to the inventory');\n\n                    this.money_to_store = 0;\n                }).catch(error => {\n                this.logError('Moving item to the inventory failed: ' + error.response.data.message);\n            });\n        },\n\n        openItemModal(item, container) {\n\n            if (!item) {\n                return;\n            }\n\n            this.itemToDisplay = item;\n            this.showModal = true;\n            this.showContainer = container;\n        },\n\n        changeItemPrice(item) {\n\n            if (!item) {\n                return;\n            }\n\n            let newPrice = item.price;\n\n            axios.post('/api/store/item/' + item.id + '/change-price', {\n                'price': newPrice,\n                'containerType': this.showContainer\n            })\n                .then(() => {\n                    this.logSuccess(item.name + ' price changed to ' + newPrice + ' coins');\n                }).catch(error => {\n                this.logError('Changing price failed: ' + error.response.data.message);\n            });\n        },\n\n        moveMoneyToInventory() {\n\n            if (this.money_to_inventory === 0) {\n                return;\n            }\n\n            this.character.inventory.money += this.money_to_inventory;\n            this.character.store.money -= this.money_to_inventory;\n\n            axios.post('/api/store/money/move-to-inventory', {'money_amount': this.money_to_inventory})\n                .then(() => {\n                    this.logSuccess('Moved: ' + this.money_to_store + ' coins to the inventory');\n\n                    this.money_to_inventory = 0;\n                }).catch(error => {\n                this.logError('Moving coins to the store failed: ' + error.response.data.message);\n            });\n        },\n\n        moveMoneyToStore() {\n\n            if (this.money_to_store === 0) {\n                return;\n            }\n\n            this.character.store.money += this.money_to_store;\n            this.character.inventory.money -= this.money_to_store;\n\n            axios.post('/api/inventory/money/move-to-store', {'money_amount': this.money_to_store})\n                .then(() => {\n                    this.logSuccess('Moved: ' + this.money_to_store + ' coins to the store');\n\n                    this.money_to_store = 0;\n                }).catch(error => {\n                this.logError('Moving coins to the store failed: ' + error.response.data.message);\n            });\n        },\n\n        asset(path) {\n            let base_path = window._asset || '';\n\n            return base_path + path;\n        },\n\n        getEquipmentItem(type) {\n            return this.character.inventory.items.find(\n                item => item.type === type && item.pivot.status === 'equipped'\n            );\n        },\n\n        getInventoryItem(index) {\n            return this.character.inventory.items.find(\n                item => parseInt(item.pivot.inventory_slot_number) === parseInt(index)\n            );\n        },\n\n        getStoreItem(index) {\n            return this.character.store.items.find(\n                item => parseInt(item.pivot.inventory_slot_number) === parseInt(index)\n            );\n        },\n\n        isEquipped(index) {\n            return this.getInventoryItem(index) && this.getInventoryItem(index).pivot.status === 'equipped';\n        },\n\n        startDrag(evt, itemIndex, container) {\n            evt.dataTransfer.dropEffect = 'move';\n            evt.dataTransfer.effectAllowed = 'move';\n\n            this.sourceContainer = container;\n\n            evt.dataTransfer.setData('itemIndex', itemIndex);\n        },\n\n        onDrop(evt, container) {\n            const itemIndex = evt.dataTransfer.getData('itemIndex');\n\n            if (container === this.sourceContainer) {\n                return;\n            }\n\n            let inventoryItem = this.getInventoryItem(itemIndex);\n\n            if (container === 'equipment') {\n                this.equipItem(inventoryItem);\n            } else {\n                this.unEquipItem(inventoryItem);\n            }\n        },\n\n        logSuccess(message) {\n            this.$root.$emit('successHappened', message);\n        },\n\n        logError(error) {\n            this.$root.$emit('errorHappened', error);\n        },\n    }\n};\n</script>\n\n<style scoped>\n.modal-item-price-image img {\n    height: 210px;\n    width: 100%;\n    background-color: black;\n}\n\n.modal-item-effects {\n    vertical-align: middle;\n    margin: 0;\n}\n\n.model-item-attributes-table th, .model-item-attributes-table td {\n    vertical-align: middle;\n    font-size: small;\n    white-space: nowrap;\n}\n</style>\n"
  },
  {
    "path": "resources/js/components/PopupModal.vue",
    "content": "<template>\n  <div>\n    <transition name=\"modal\">\n      <div class=\"modal-mask\">\n        <div class=\"modal-wrapper\" @click.stop.prevent=\"$emit('closeModal')\">\n          <div class=\"modal-container\" @click.stop>\n\n            <div class=\"modal-body\">\n              <slot name=\"body\"></slot>\n            </div>\n\n          </div>\n        </div>\n      </div>\n    </transition>\n  </div>\n</template>\n\n<script>\nexport default {\n  mounted() {\n\n  },\n\n  data() {\n    return {};\n  }\n}\n</script>\n\n<style scoped>\n.modal-mask {\n  position: fixed;\n  z-index: 9998;\n  top: 0;\n  left: 0;\n  width: 100%;\n  height: 100%;\n  background-color: rgba(0, 0, 0, 0.5);\n  display: table;\n  transition: opacity 0.3s ease;\n}\n\n.modal-wrapper {\n  display: table-cell;\n  vertical-align: middle;\n}\n\n.modal-container {\n  width: 240px;\n  margin: 0 auto;\n  background-color: #fff;\n  border-radius: 2px;\n  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.33);\n  transition: all 0.3s ease;\n  font-family: Helvetica, Arial, sans-serif;\n}\n\n.modal-enter {\n  opacity: 0;\n}\n\n.modal-leave-active {\n  opacity: 0;\n}\n\n.modal-enter .modal-container,\n.modal-leave-active .modal-container {\n  -webkit-transform: scale(1.1);\n  transform: scale(1.1);\n}\n\n</style>\n"
  },
  {
    "path": "resources/js/components/StoreManagement.vue",
    "content": "<template>\n    <div>\n\n        <div class=\"row\">\n            <popup-modal v-if=\"showModal\" @closeModal=\"showModal = false\">\n\n                <div slot=\"body\">\n\n                    <div class=\"font-weight-bold\">\n                        {{ itemToDisplay.name }}\n\n                        <button type=\"submit\"\n                                class=\"close\"\n                                @click.stop.prevent=\"showModal = false\">\n                            x\n                        </button>\n                    </div>\n\n                    <div class=\"modal-item-price-image\">\n                        <img :src=\"'/' + itemToDisplay.image_file_path\" :alt=\"itemToDisplay.name\">\n                    </div>\n\n                    <table class=\"table model-item-attributes-table\">\n                        <caption class=\"caption-top\">Attributes</caption>\n                        <tr>\n                            <th scope=\"row\">Sell price</th>\n                            <td>\n                                <form>\n                                    <label for=\"set-item-price\"></label>\n                                    <input type=\"number\"\n                                           name=\"money_amount\"\n                                           id=\"set-item-price\"\n                                           class=\"w-100\"\n                                           v-model.number=\"itemToDisplay.price\"\n                                           @change.stop.prevent=\"changeItemPrice(itemToDisplay)\"\n                                           min=\"0\"\n                                           aria-label=\"Set item price\">\n                                </form>\n                            </td>\n                        </tr>\n                        <tr>\n                            <th scope=\"row\">Type</th>\n                            <td>{{ itemToDisplay.type | underscoreToWhitespace | capitalize }}</td>\n                        </tr>\n                        <tr>\n                            <th scope=\"row\">Effects</th>\n                            <td>\n                                <ul class=\"list-unstyled modal-item-effects\">\n                                    <li v-for=\"effect in itemToDisplay.effects\" class=\"\" :key=\"effect.type\">\n                                        {{ effect.type | capitalize }}: {{ effect.quantity | plusForPositiveNumber }}\n                                    </li>\n                                </ul>\n                            </td>\n                        </tr>\n                    </table>\n                </div>\n\n            </popup-modal>\n        </div>\n\n        <div class=\"row\">\n\n            <!-- Left Side -->\n            <div class=\"col-md-6\">\n\n                <h5 class=\"text-center\">\n                    {{ character.name }}'s Inventory\n                </h5>\n\n                <div class=\"my-3 row mx-1 table-dark align-items-center\">\n\n                    <div v-for=\"index in total_inventory_slots\" :key=\"index\"\n                         :id=\"index-1\"\n                         :class=\"[isEquipped(index-1) ? 'inventory-item equipped' : 'inventory-item']\"\n                         @drop=\"onDrop($event, 'inventory')\"\n                         @dragover.prevent\n                         @dragenter.prevent>\n                        <button type=\"submit\"\n                                @click.stop.prevent=\"openItemModal(getInventoryItem(index-1), 'inventory')\"\n                                @dragstart=\"startDrag($event, index-1, 'inventory')\"\n                                draggable=\"true\"\n                                class=\"btn btn-link-thin\"\n                                v-if=\"getInventoryItem(index-1)\">\n                            <img :src=\"asset(getInventoryItem(index-1).image_file_path)\"\n                                 :alt=\"getInventoryItem(index-1).name\">\n                        </button>\n                    </div>\n\n                </div>\n\n            </div>\n\n            <!-- Right Side -->\n            <div class=\"col-md-6\">\n\n                <h5 class=\"text-center\">\n                    {{ character.name }}'s Store ({{ character.store.type | underscoreToWhitespace | capitalize }})\n                </h5>\n\n                <div class=\"my-3 row mx-1 table-dark align-items-center\">\n\n                    <div v-for=\"index in total_store_slots\" :key=\"index\"\n                         :id=\"index-1\"\n                         class=\"inventory-item\"\n                         @drop=\"onDrop($event, 'store')\"\n                         @dragover.prevent\n                         @dragenter.prevent>\n                        <button type=\"submit\"\n                                @click.stop.prevent=\"openItemModal(getStoreItem(index-1), 'store')\"\n                                class=\"btn btn-link-thin\"\n                                @dragstart=\"startDrag($event, index-1, 'store')\"\n                                draggable=\"true\"\n                                v-if=\"getStoreItem(index-1)\">\n                            <img :src=\"asset(getStoreItem(index-1).image_file_path)\" :alt=\"getStoreItem(index-1).name\">\n                        </button>\n                    </div>\n\n                </div>\n\n            </div>\n        </div>\n\n        <div class=\"row\">\n\n            <!-- Left Side -->\n            <div class=\"col-md-6\">\n                <div class=\"row\">\n                    <div class=\"col-md-12 text-center my-3\">\n                        <div class=\"input-group mb-3\">\n                            <div class=\"input-group-prepend\">\n                                <span class=\"input-group-text font-weight-bold\">\n                                    Money in inventory: {{ character.inventory.money }}\n                                </span>\n                            </div>\n                            <label for=\"money-to-store\"></label>\n                            <input type=\"number\"\n                                   name=\"money_amount\"\n                                   id=\"money-to-store\"\n                                   class=\"form-control\"\n                                   v-model.number=\"money_to_store\"\n                                   min=\"0\"\n                                   :max=character.inventory.money\n                                   aria-label=\"Money to move to store\">\n                            <div class=\"input-group-append\">\n                                <span class=\"input-group-text\">\n                                    <button type=\"submit\"\n                                            class=\"btn btn-sm btn-secondary\"\n                                            @click.stop.prevent=\"moveMoneyToStore()\">\n                                        Move to Store\n                                         <span class=\"fas fa-long-arrow-alt-right\"></span>\n                                    </button>\n                                </span>\n                            </div>\n                        </div>\n                    </div>\n                </div>\n            </div>\n\n            <!-- Right Side -->\n            <div class=\"col-md-6\">\n                <div class=\"row\">\n                    <div class=\"col-md-12 text-center my-3\">\n                        <div class=\"input-group mb-3\">\n                            <div class=\"input-group-prepend\">\n                                <span class=\"input-group-text\">\n                                    <button type=\"submit\"\n                                            class=\"btn btn-sm btn-secondary\"\n                                            @click.stop.prevent=\"moveMoneyToInventory()\">\n                                        <span class=\"fas fa-long-arrow-alt-left\"></span>\n                                        Move to Inventory\n                                    </button>\n                                </span>\n                            </div>\n                            <label for=\"money-to-inventory\"></label>\n                            <input type=\"number\"\n                                   name=\"money_amount\"\n                                   id=\"money-to-inventory\"\n                                   class=\"form-control\"\n                                   v-model.number=\"money_to_inventory\"\n                                   min=\"0\"\n                                   :max=character.store.money\n                                   aria-label=\"Money to move to inventory\">\n                            <div class=\"input-group-append\">\n                                <span class=\"input-group-text font-weight-bold\">\n                                    Money in store: {{ character.store.money }}\n                                </span>\n                            </div>\n                        </div>\n                    </div>\n                </div>\n            </div>\n\n        </div>\n\n    </div>\n</template>\n\n<script>\n\nexport default {\n    mounted() {\n\n    },\n\n    data() {\n        return {\n            itemToDisplay: {\n                pivot: {\n                    inventory_slot_number: null,\n                    status: ''\n                },\n                image_file_path: '',\n                price: 0,\n                type: '',\n                name: '',\n                effects: {\n                    quantity: 0,\n                    type: ''\n                }\n            },\n            showModal: false,\n            showContainer: 'inventory',\n            sourceContainer: 'inventory',\n            money_to_store: 0,\n            money_to_inventory: 0,\n            total_inventory_slots: 25,\n            total_store_slots: 25,\n            character: {\n                name: '',\n                inventory: {\n                    items: [\n                        {\n                            pivot: {\n                                inventory_slot_number: null,\n                                status: ''\n                            },\n                            image_file_path: '',\n                            price: 0,\n                            type: '',\n                            name: '',\n                            effects: {\n                                quantity: 0,\n                                type: ''\n                            }\n                        }\n                    ],\n                    money: 0\n                },\n                store: {\n                    items: [\n                        {\n                            pivot: {\n                                inventory_slot_number: null,\n                                status: ''\n                            },\n                            image_file_path: '',\n                            price: 0,\n                            type: '',\n                            name: '',\n                            effects: {\n                                quantity: 0,\n                                type: ''\n                            }\n                        }\n                    ],\n                    money: 0,\n                    type: null\n                }\n            }\n        }\n    },\n\n    created() {\n        this.character = this.$attrs.character;\n    },\n\n    methods: {\n        findFreeStoreSlot() {\n\n            for (let slot = 0; slot < this.total_store_slots; slot++) {\n\n                if (this.getStoreItem(slot) === undefined) {\n                    return slot;\n                }\n            }\n\n            return null;\n        },\n\n        findFreeInventorySlot() {\n\n            for (let slot = 0; slot < this.total_inventory_slots; slot++) {\n\n                if (this.getInventoryItem(slot) === undefined) {\n                    return slot;\n                }\n            }\n\n            return null;\n        },\n\n        moveItemToStore(item) {\n\n            if (!item) {\n                return;\n            }\n\n            this.showModal = false;\n\n            item.pivot.inventory_slot_number = this.findFreeStoreSlot();\n            item.pivot.status = 'in_backpack';\n\n            this.character.store.items.push(item);\n\n            let index = this.character.inventory.items.indexOf(item);\n\n            if (index > -1) {\n                this.character.inventory.items.splice(index, 1);\n            }\n\n            axios.post('/api/inventory/item/' + item.id + '/move-to-store')\n                .then(() => {\n                    this.logSuccess('Moved: ' + item.name + ' to the store');\n\n                    this.money_to_store = 0;\n                }).catch(error => {\n                this.logError('Moving item to the store failed: ' + error.response.data.message);\n            });\n        },\n\n        moveItemToInventory(item) {\n\n            if (!item) {\n                return;\n            }\n\n            item.pivot.inventory_slot_number = this.findFreeInventorySlot();\n\n            this.character.inventory.items.push(item);\n\n            let index = this.character.store.items.indexOf(item);\n\n            if (index > -1) {\n                this.character.store.items.splice(index, 1);\n            }\n\n            axios.post('/api/store/item/' + item.id + '/move-to-inventory')\n                .then(() => {\n                    this.logSuccess('Moved: ' + item.name + ' to the inventory');\n\n                    this.money_to_store = 0;\n                }).catch(error => {\n                this.logError('Moving item to the inventory failed: ' + error.response.data.message);\n            });\n        },\n\n        openItemModal(item, container) {\n\n            if (!item) {\n                return;\n            }\n\n            this.itemToDisplay = item;\n            this.showModal = true;\n            this.showContainer = container;\n        },\n\n        changeItemPrice(item) {\n\n            if (!item) {\n                return;\n            }\n\n            let newPrice = item.price;\n\n            axios.post('/api/store/item/' + item.id + '/change-price', {\n                'price': newPrice,\n                'containerType': this.showContainer\n            })\n                .then(() => {\n                    this.logSuccess(item.name + ' price changed to ' + newPrice + ' coins');\n                }).catch(error => {\n                this.logError('Changing price failed: ' + error.response.data.message);\n            });\n        },\n\n        moveMoneyToInventory() {\n\n            if (this.money_to_inventory === 0) {\n                return;\n            }\n\n            this.character.inventory.money += this.money_to_inventory;\n            this.character.store.money -= this.money_to_inventory;\n\n            axios.post('/api/store/money/move-to-inventory', {'money_amount': this.money_to_inventory})\n                .then(() => {\n                    this.logSuccess('Moved: ' + this.money_to_store + ' coins to the inventory');\n\n                    this.money_to_inventory = 0;\n                }).catch(error => {\n                this.logError('Moving coins to the store failed: ' + error.response.data.message);\n            });\n        },\n\n        moveMoneyToStore() {\n\n            if (this.money_to_store === 0) {\n                return;\n            }\n\n            this.character.store.money += this.money_to_store;\n            this.character.inventory.money -= this.money_to_store;\n\n            axios.post('/api/inventory/money/move-to-store', {'money_amount': this.money_to_store})\n                .then(() => {\n                    this.logSuccess('Moved: ' + this.money_to_store + ' coins to the store');\n\n                    this.money_to_store = 0;\n                }).catch(error => {\n                this.logError('Moving coins to the store failed: ' + error.response.data.message);\n            });\n        },\n\n        asset(path) {\n            let base_path = window._asset || '';\n\n            return base_path + path;\n        },\n\n        getInventoryItem(index) {\n            return this.character.inventory.items.find(\n                item => parseInt(item.pivot.inventory_slot_number) === parseInt(index)\n            );\n        },\n\n        getStoreItem(index) {\n            return this.character.store.items.find(\n                item => parseInt(item.pivot.inventory_slot_number) === parseInt(index)\n            );\n        },\n\n        isEquipped(index) {\n            return this.getInventoryItem(index) && this.getInventoryItem(index).pivot.status === 'equipped';\n        },\n\n        startDrag(evt, itemIndex, container) {\n            evt.dataTransfer.dropEffect = 'move';\n            evt.dataTransfer.effectAllowed = 'move';\n\n            this.sourceContainer = container;\n\n            evt.dataTransfer.setData('itemIndex', itemIndex);\n        },\n\n        onDrop(evt, container) {\n            const itemIndex = evt.dataTransfer.getData('itemIndex');\n\n            if (container === this.sourceContainer) {\n                return;\n            }\n\n            if (container === 'store') {\n                let inventoryItem = this.getInventoryItem(itemIndex);\n\n                this.moveItemToStore(inventoryItem);\n            } else {\n\n                let storeItem = this.getStoreItem(itemIndex);\n\n                this.moveItemToInventory(storeItem);\n            }\n        },\n\n        logSuccess(message) {\n            this.$root.$emit('successHappened', message);\n        },\n\n        logError(error) {\n            this.$root.$emit('errorHappened', error);\n        },\n    }\n};\n</script>\n\n<style scoped>\n.modal-item-price-image img {\n    height: 210px;\n    width: 100%;\n    background-color: black;\n}\n\n.modal-item-effects {\n    vertical-align: middle;\n    margin: 0;\n}\n\n.model-item-attributes-table th, .model-item-attributes-table td {\n    vertical-align: middle;\n    font-size: small;\n    white-space: nowrap;\n}\n</style>\n"
  },
  {
    "path": "resources/js/components/StoreTrade.vue",
    "content": "<template>\n    <div>\n\n        <div class=\"row\">\n            <popup-modal v-if=\"showModal\" @closeModal=\"showModal = false\">\n\n                <div slot=\"body\">\n\n                    <div class=\"font-weight-bold\">\n\n                        <button type=\"submit\"\n                                class=\"close\"\n                                @click.stop.prevent=\"showModal = false\">\n                            x\n                        </button>\n\n                        {{ itemToDisplay.name }}\n                        <br>(\n                            <small v-if=\"showContainer == 'inventory'\">{{ customer.name }}'s Inventory</small>\n                            <small v-else>{{ trader.name }}'s Store</small>\n                        )\n                    </div>\n\n                    <div class=\"modal-item-price-image\">\n                        <img :src=\"'/' + itemToDisplay.image_file_path\" :alt=\"itemToDisplay.name\">\n                    </div>\n\n                    <table class=\"table model-item-attributes-table\">\n                        <caption class=\"caption-top\">Attributes</caption>\n                        <tr>\n                            <th scope=\"row\">Sell price</th>\n                            <td v-if=\"showContainer == 'inventory'\">\n                                <form >\n                                    <label for=\"set-item-price\"></label>\n                                    <input type=\"number\"\n                                           name=\"money_amount\"\n                                           id=\"set-item-price\"\n                                           class=\"w-100\"\n                                           v-model.number=\"itemToDisplay.price\"\n                                           @change.stop.prevent=\"changeItemPrice(itemToDisplay)\"\n                                           min=\"0\"\n                                           aria-label=\"Set item price\">\n                                </form>\n                            </td>\n                            <td v-else>\n                                {{ itemToDisplay.price }}\n                            </td>\n                        </tr>\n                        <tr v-if=\"showContainer == 'inventory'\">\n                            <th scope=\"row\">Store buy price</th>\n                            <td>\n                                {{ toStoreBuyPrice(itemToDisplay) }}\n                            </td>\n                        </tr>\n                        <tr>\n                            <th scope=\"row\">Type</th>\n                            <td>{{ itemToDisplay.type | underscoreToWhitespace | capitalize }}</td>\n                        </tr>\n                        <tr>\n                            <th scope=\"row\">Effects</th>\n                            <td>\n                                <ul class=\"list-unstyled modal-item-effects\">\n                                    <li v-for=\"effect in itemToDisplay.effects\" class=\"\" :key=\"effect.type\">\n                                        {{ effect.type | capitalize }}: {{ effect.quantity | plusForPositiveNumber }}\n                                    </li>\n                                </ul>\n                            </td>\n                        </tr>\n                    </table>\n                </div>\n\n            </popup-modal>\n        </div>\n\n        <div class=\"row\">\n\n            <!-- Left Side -->\n            <div class=\"col-md-6\">\n\n                <h5 class=\"text-center\">\n                    {{ customer.name }}'s Inventory\n                </h5>\n\n                <div class=\"my-3 row mx-1 table-dark align-items-center\">\n\n                    <div v-for=\"index in total_inventory_slots\" :key=\"index\"\n                         :id=\"index-1\"\n                         :class=\"[isEquipped(index-1) ? 'inventory-item equipped' : 'inventory-item']\"\n                         @drop=\"onDrop($event, 'inventory')\"\n                         @dragover.prevent\n                         @dragenter.prevent>\n                        <button type=\"submit\"\n                                @click.stop.prevent=\"openItemModal(getInventoryItem(index-1), 'inventory')\"\n                                @dragstart=\"startDrag($event, index-1, 'inventory')\"\n                                draggable=\"true\"\n                                class=\"btn btn-link-thin\"\n                                v-if=\"getInventoryItem(index-1)\">\n                            <img :src=\"asset(getInventoryItem(index-1).image_file_path)\"\n                                 :alt=\"getInventoryItem(index-1).name\">\n                        </button>\n                    </div>\n\n                </div>\n\n            </div>\n\n            <!-- Right Side -->\n            <div class=\"col-md-6\">\n\n                <h5 class=\"text-center\">\n                    {{ trader.name }}'s Store ({{ trader.store.type | underscoreToWhitespace | capitalize }})\n                </h5>\n\n                <div class=\"my-3 row mx-1 table-dark align-items-center\">\n\n                    <div v-for=\"index in total_store_slots\" :key=\"index\"\n                         :id=\"index-1\"\n                         class=\"inventory-item\"\n                         @drop=\"onDrop($event, 'store')\"\n                         @dragover.prevent\n                         @dragenter.prevent>\n                        <button type=\"submit\"\n                                @click.stop.prevent=\"openItemModal(getStoreItem(index-1), 'store')\"\n                                class=\"btn btn-link-thin\"\n                                @dragstart=\"startDrag($event, index-1, 'store')\"\n                                draggable=\"true\"\n                                v-if=\"getStoreItem(index-1)\">\n                            <img :src=\"asset(getStoreItem(index-1).image_file_path)\" :alt=\"getStoreItem(index-1).name\">\n                        </button>\n                    </div>\n\n                </div>\n\n            </div>\n        </div>\n\n        <div class=\"row\">\n\n            <!-- Left Side -->\n            <div class=\"col-md-6\">\n                <div class=\"row\">\n                    <div class=\"col-md-12 text-center my-3\">\n                        <div class=\"input-group mb-3\">\n                            <div class=\"input-group-prepend\">\n                                <span class=\"input-group-text font-weight-bold\">\n                                    Money in inventory: {{ customer.inventory.money }}\n                                </span>\n                            </div>\n                        </div>\n                    </div>\n                </div>\n            </div>\n\n            <!-- Right Side -->\n            <div class=\"col-md-6\">\n                <div class=\"row\">\n                    <div class=\"col-md-12 text-center my-3\">\n                        <div class=\"input-group mb-3\">\n                            <div class=\"input-group-append\">\n                                <span class=\"input-group-text font-weight-bold\">\n                                    Money in store: {{ trader.store.money }}\n                                </span>\n                            </div>\n                        </div>\n                    </div>\n                </div>\n            </div>\n\n        </div>\n\n    </div>\n</template>\n\n<script>\n\nexport default {\n    mounted() {\n\n    },\n\n    data() {\n        return {\n            itemToDisplay: {\n                pivot: {\n                    inventory_slot_number: null,\n                    status: ''\n                },\n                image_file_path: '',\n                price: 0,\n                type: '',\n                name: '',\n                effects: {\n                    quantity: 0,\n                    type: ''\n                },\n                prototype: {\n                    price: 0\n                }\n            },\n            showModal: false,\n            showContainer: 'inventory',\n            sourceContainer: 'inventory',\n            money_to_store: 0,\n            money_to_inventory: 0,\n            total_inventory_slots: 25,\n            total_store_slots: 25,\n            customer: {\n                name: '',\n                inventory: {\n                    items: [\n                        {\n                            pivot: {\n                                inventory_slot_number: null,\n                                status: ''\n                            },\n                            image_file_path: '',\n                            price: 0,\n                            type: '',\n                            name: '',\n                            effects: {\n                                quantity: 0,\n                                type: ''\n                            },\n                            prototype: {\n                                price: 0\n                            }\n                        }\n                    ],\n                    money: 0\n                },\n            },\n            trader: {\n                name: '',\n                store: {\n                    id: '',\n                    items: [\n                        {\n                            pivot: {\n                                inventory_slot_number: null,\n                                status: ''\n                            },\n                            image_file_path: '',\n                            price: 0,\n                            type: '',\n                            name: '',\n                            effects: {\n                                quantity: 0,\n                                type: ''\n                            },\n                            prototype: {\n                                price: 0\n                            }\n                        }\n                    ],\n                    money: 0,\n                    type: null\n                }\n            }\n        }\n    },\n\n    created() {\n        this.customer = this.$attrs.customer;\n        this.trader = this.$attrs.trader;\n    },\n\n    methods: {\n\n        buy(item) {\n\n            if (!item) {\n                this.logError('Item not found');\n\n                return;\n            }\n\n            if (this.customer.inventory.money < item.price) {\n                this.logError('You don\\'t have ' + item.price + ' coins');\n\n                return;\n            }\n\n            this.exchangeMoneyForItem(item);\n\n            axios.post('/api/store/' + this.trader.store.id + '/item/' + item.id + '/buy')\n                .then(() => {\n                    this.logSuccess('Bought: ' + item.name + ' for ' + item.price + ' coins');\n                }).catch(error => {\n                this.exchangeItemForMoney(item);\n                this.logError(error.response.data.message);\n            });\n        },\n\n        sell(item) {\n\n            if (!item) {\n                return;\n            }\n\n            if (this.trader.store.type === 'sell_only') {\n                this.logError('This store only sell items - find a merchant store instead');\n\n                return;\n            }\n\n            if (this.trader.store.money < item.price) {\n                this.logError('The store doesn\\'t have ' + item.price + ' coins');\n\n                return;\n            }\n\n            if (item.prototype.price < item.price) {\n                this.logError('The store is willing to pay no more than ' + item.prototype.price + ' coins for ' + item.name);\n\n                return;\n            }\n\n            this.exchangeItemForMoney(item);\n\n            axios.post('/api/store/' + this.trader.store.id + '/item/' + item.id + '/sell')\n                .then(() => {\n                    this.logSuccess('Sold: ' + item.name + ' for ' + item.price + ' coins');\n                    item.price = item.prototype.price;\n                }).catch(error => {\n                this.exchangeMoneyForItem(item);\n                this.logError(error.response.data.message);\n            });\n        },\n\n        exchangeMoneyForItem: function (item) {\n            item.pivot.inventory_slot_number = this.findFreeInventorySlot();\n\n            this.customer.inventory.items.push(item);\n\n            let index = this.trader.store.items.indexOf(item);\n\n            if (index > -1) {\n                this.trader.store.items.splice(index, 1);\n            }\n\n            this.customer.inventory.money -= item.price;\n            this.trader.store.money += item.price\n        },\n\n        exchangeItemForMoney: function (item) {\n\n            item.pivot.inventory_slot_number = this.findFreeStoreSlot();\n\n            this.trader.store.items.push(item);\n\n            let index = this.customer.inventory.items.indexOf(item);\n\n            if (index > -1) {\n                this.customer.inventory.items.splice(index, 1);\n            }\n\n            this.trader.store.money -= item.price;\n            this.customer.inventory.money += item.price\n        },\n\n        findFreeStoreSlot() {\n\n            for (let slot = 0; slot < this.total_store_slots; slot++) {\n\n                if (this.getStoreItem(slot) === undefined) {\n                    return slot;\n                }\n            }\n\n            return null;\n        },\n\n        findFreeInventorySlot() {\n\n            for (let slot = 0; slot < this.total_inventory_slots; slot++) {\n\n                if (this.getInventoryItem(slot) === undefined) {\n                    return slot;\n                }\n            }\n\n            return null;\n        },\n\n        openItemModal(item, container) {\n\n            if (!item) {\n                return;\n            }\n\n            this.itemToDisplay = item;\n            this.showModal = true;\n            this.showContainer = container;\n        },\n\n        changeItemPrice(item) {\n            if (!item) {\n                return;\n            }\n\n            let newPrice = item.price;\n\n            axios.post('/api/store/item/' + item.id + '/change-price', {\n                'price': newPrice,\n                'containerType': this.showContainer\n            })\n                .then(() => {\n                    this.logSuccess(item.name + ' price changed to ' + newPrice + ' coins');\n                }).catch(error => {\n                this.logError('Changing price failed: ' + error.response.data.message);\n            });\n        },\n\n        asset(path) {\n            let base_path = window._asset || '';\n\n            return base_path + path;\n        },\n\n        getInventoryItem(index) {\n            return this.customer.inventory.items.find(\n                item => parseInt(item.pivot.inventory_slot_number) === parseInt(index)\n            );\n        },\n\n        getStoreItem(index) {\n            return this.trader.store.items.find(\n                item => parseInt(item.pivot.inventory_slot_number) === parseInt(index)\n            );\n        },\n\n        isEquipped(index) {\n            return this.getInventoryItem(index) && this.getInventoryItem(index).pivot.status === 'equipped';\n        },\n\n        toStoreBuyPrice(item) {\n            return Math.floor(item.prototype.price * 0.75);\n        },\n\n        startDrag(evt, itemIndex, container) {\n            evt.dataTransfer.dropEffect = 'move';\n            evt.dataTransfer.effectAllowed = 'move';\n\n            this.sourceContainer = container;\n\n            evt.dataTransfer.setData('itemIndex', itemIndex);\n        },\n\n        onDrop(evt, container) {\n            const itemIndex = evt.dataTransfer.getData('itemIndex');\n\n            if (container === this.sourceContainer) {\n                return;\n            }\n\n            if (container === 'store') {\n                let inventoryItem = this.getInventoryItem(itemIndex);\n\n                this.sell(inventoryItem);\n            } else {\n\n                let storeItem = this.getStoreItem(itemIndex);\n\n                this.buy(storeItem);\n            }\n        },\n\n        logSuccess(message) {\n            this.$root.$emit('successHappened', message);\n        },\n\n        logError(error) {\n            this.$root.$emit('errorHappened', error);\n        },\n    }\n};\n</script>\n\n<style scoped>\n.modal-item-price-image img {\n    height: 210px;\n    width: 100%;\n    background-color: black;\n}\n\n.modal-item-effects {\n    vertical-align: middle;\n    margin: 0;\n}\n\n.model-item-attributes-table th, .model-item-attributes-table td {\n    vertical-align: middle;\n    font-size: small;\n    white-space: nowrap;\n}\n</style>\n"
  },
  {
    "path": "resources/lang/en/auth.php",
    "content": "<?php\n\nreturn [\n\n    /*\n    |--------------------------------------------------------------------------\n    | Authentication Language Lines\n    |--------------------------------------------------------------------------\n    |\n    | The following language lines are used during authentication for various\n    | messages that we need to display to the user. You are free to modify\n    | these language lines according to your application's requirements.\n    |\n    */\n\n    'failed' => 'These credentials do not match our records.',\n    'password' => 'The provided password is incorrect.',\n    'throttle' => 'Too many login attempts. Please try again in :seconds seconds.',\n\n];\n"
  },
  {
    "path": "resources/lang/en/pagination.php",
    "content": "<?php\n\nreturn [\n\n    /*\n    |--------------------------------------------------------------------------\n    | Pagination Language Lines\n    |--------------------------------------------------------------------------\n    |\n    | The following language lines are used by the paginator library to build\n    | the simple pagination links. You are free to change them to anything\n    | you want to customize your views to better match your application.\n    |\n    */\n\n    'previous' => '&laquo; Previous',\n    'next' => 'Next &raquo;',\n\n];\n"
  },
  {
    "path": "resources/lang/en/passwords.php",
    "content": "<?php\n\nreturn [\n\n    /*\n    |--------------------------------------------------------------------------\n    | Password Reset Language Lines\n    |--------------------------------------------------------------------------\n    |\n    | The following language lines are the default lines which match reasons\n    | that are given by the password broker for a password update attempt\n    | has failed, such as for an invalid token or invalid new password.\n    |\n    */\n\n    'reset' => 'Your password has been reset!',\n    'sent' => 'We have emailed your password reset link!',\n    'throttled' => 'Please wait before retrying.',\n    'token' => 'This password reset token is invalid.',\n    'user' => \"We can't find a user with that email address.\",\n\n];"
  },
  {
    "path": "resources/lang/en/validation.php",
    "content": "<?php\n\nreturn [\n\n    /*\n    |--------------------------------------------------------------------------\n    | Validation Language Lines\n    |--------------------------------------------------------------------------\n    |\n    | The following language lines contain the default error messages used by\n    | the validator class. Some of these rules have multiple versions such\n    | as the size rules. Feel free to tweak each of these messages here.\n    |\n    */\n\n    'accepted' => 'The :attribute must be accepted.',\n    'active_url' => 'The :attribute is not a valid URL.',\n    'after' => 'The :attribute must be a date after :date.',\n    'after_or_equal' => 'The :attribute must be a date after or equal to :date.',\n    'alpha' => 'The :attribute must only contain letters.',\n    'alpha_dash' => 'The :attribute must only contain letters, numbers, dashes and underscores.',\n    'alpha_num' => 'The :attribute must only contain letters and numbers.',\n    'array' => 'The :attribute must be an array.',\n    'before' => 'The :attribute must be a date before :date.',\n    'before_or_equal' => 'The :attribute must be a date before or equal to :date.',\n    'between' => [\n        'numeric' => 'The :attribute must be between :min and :max.',\n        'file' => 'The :attribute must be between :min and :max kilobytes.',\n        'string' => 'The :attribute must be between :min and :max characters.',\n        'array' => 'The :attribute must have between :min and :max items.',\n    ],\n    'boolean' => 'The :attribute field must be true or false.',\n    'confirmed' => 'The :attribute confirmation does not match.',\n    'date' => 'The :attribute is not a valid date.',\n    'date_equals' => 'The :attribute must be a date equal to :date.',\n    'date_format' => 'The :attribute does not match the format :format.',\n    'different' => 'The :attribute and :other must be different.',\n    'digits' => 'The :attribute must be :digits digits.',\n    'digits_between' => 'The :attribute must be between :min and :max digits.',\n    'dimensions' => 'The :attribute has invalid image dimensions.',\n    'distinct' => 'The :attribute field has a duplicate value.',\n    'email' => 'The :attribute must be a valid email address.',\n    'ends_with' => 'The :attribute must end with one of the following: :values.',\n    'exists' => 'The selected :attribute is invalid.',\n    'file' => 'The :attribute must be a file.',\n    'filled' => 'The :attribute field must have a value.',\n    'gt' => [\n        'numeric' => 'The :attribute must be greater than :value.',\n        'file' => 'The :attribute must be greater than :value kilobytes.',\n        'string' => 'The :attribute must be greater than :value characters.',\n        'array' => 'The :attribute must have more than :value items.',\n    ],\n    'gte' => [\n        'numeric' => 'The :attribute must be greater than or equal :value.',\n        'file' => 'The :attribute must be greater than or equal :value kilobytes.',\n        'string' => 'The :attribute must be greater than or equal :value characters.',\n        'array' => 'The :attribute must have :value items or more.',\n    ],\n    'image' => 'The :attribute must be an image.',\n    'in' => 'The selected :attribute is invalid.',\n    'in_array' => 'The :attribute field does not exist in :other.',\n    'integer' => 'The :attribute must be an integer.',\n    'ip' => 'The :attribute must be a valid IP address.',\n    'ipv4' => 'The :attribute must be a valid IPv4 address.',\n    'ipv6' => 'The :attribute must be a valid IPv6 address.',\n    'json' => 'The :attribute must be a valid JSON string.',\n    'lt' => [\n        'numeric' => 'The :attribute must be less than :value.',\n        'file' => 'The :attribute must be less than :value kilobytes.',\n        'string' => 'The :attribute must be less than :value characters.',\n        'array' => 'The :attribute must have less than :value items.',\n    ],\n    'lte' => [\n        'numeric' => 'The :attribute must be less than or equal :value.',\n        'file' => 'The :attribute must be less than or equal :value kilobytes.',\n        'string' => 'The :attribute must be less than or equal :value characters.',\n        'array' => 'The :attribute must not have more than :value items.',\n    ],\n    'max' => [\n        'numeric' => 'The :attribute must not be greater than :max.',\n        'file' => 'The :attribute must not be greater than :max kilobytes.',\n        'string' => 'The :attribute must not be greater than :max characters.',\n        'array' => 'The :attribute must not have more than :max items.',\n    ],\n    'mimes' => 'The :attribute must be a file of type: :values.',\n    'mimetypes' => 'The :attribute must be a file of type: :values.',\n    'min' => [\n        'numeric' => 'The :attribute must be at least :min.',\n        'file' => 'The :attribute must be at least :min kilobytes.',\n        'string' => 'The :attribute must be at least :min characters.',\n        'array' => 'The :attribute must have at least :min items.',\n    ],\n    'multiple_of' => 'The :attribute must be a multiple of :value.',\n    'not_in' => 'The selected :attribute is invalid.',\n    'not_regex' => 'The :attribute format is invalid.',\n    'numeric' => 'The :attribute must be a number.',\n    'password' => 'The password is incorrect.',\n    'present' => 'The :attribute field must be present.',\n    'regex' => 'The :attribute format is invalid.',\n    'required' => 'The :attribute field is required.',\n    'required_if' => 'The :attribute field is required when :other is :value.',\n    'required_unless' => 'The :attribute field is required unless :other is in :values.',\n    'required_with' => 'The :attribute field is required when :values is present.',\n    'required_with_all' => 'The :attribute field is required when :values are present.',\n    'required_without' => 'The :attribute field is required when :values is not present.',\n    'required_without_all' => 'The :attribute field is required when none of :values are present.',\n    'prohibited' => 'The :attribute field is prohibited.',\n    'prohibited_if' => 'The :attribute field is prohibited when :other is :value.',\n    'prohibited_unless' => 'The :attribute field is prohibited unless :other is in :values.',\n    'same' => 'The :attribute and :other must match.',\n    'size' => [\n        'numeric' => 'The :attribute must be :size.',\n        'file' => 'The :attribute must be :size kilobytes.',\n        'string' => 'The :attribute must be :size characters.',\n        'array' => 'The :attribute must contain :size items.',\n    ],\n    'starts_with' => 'The :attribute must start with one of the following: :values.',\n    'string' => 'The :attribute must be a string.',\n    'timezone' => 'The :attribute must be a valid zone.',\n    'unique' => 'The :attribute has already been taken.',\n    'uploaded' => 'The :attribute failed to upload.',\n    'url' => 'The :attribute format is invalid.',\n    'uuid' => 'The :attribute must be a valid UUID.',\n\n    /*\n    |--------------------------------------------------------------------------\n    | Custom Validation Language Lines\n    |--------------------------------------------------------------------------\n    |\n    | Here you may specify custom validation messages for attributes using the\n    | convention \"attribute.rule\" to name the lines. This makes it quick to\n    | specify a specific custom language line for a given attribute rule.\n    |\n    */\n\n    'custom' => [\n        'attribute-name' => [\n            'rule-name' => 'custom-message',\n        ],\n    ],\n\n    /*\n    |--------------------------------------------------------------------------\n    | Custom Validation Attributes\n    |--------------------------------------------------------------------------\n    |\n    | The following language lines are used to swap our attribute placeholder\n    | with something more reader friendly such as \"E-Mail Address\" instead\n    | of \"email\". This simply helps us make our message more expressive.\n    |\n    */\n\n    'attributes' => [],\n\n];\n"
  },
  {
    "path": "resources/sass/_variables.scss",
    "content": "// Body\n$body-bg: #f8fafc;\n\n// Typography\n$font-family-sans-serif: 'Nunito', sans-serif;\n$font-size-base: 0.9rem;\n$line-height-base: 1.6;\n\n// Colors\n$blue: #3490dc;\n$indigo: #6574cd;\n$purple: #9561e2;\n$pink: #f66d9b;\n$red: #e3342f;\n$orange: #f6993f;\n$yellow: #ffed4a;\n$green: #38c172;\n$teal: #4dc0b5;\n$cyan: #6cb2eb;\n"
  },
  {
    "path": "resources/sass/app.scss",
    "content": "// Fonts\n@import url('https://fonts.googleapis.com/css?family=Nunito');\n\n// Variables\n@import 'variables';\n\n// Bootstrap\n@import '~bootstrap/scss/bootstrap';\n\n// Bootstrap\n@import '~@fortawesome/fontawesome-free/css/all.min.css';\n\n// Custom css\n@import \"custom.scss\";\n"
  },
  {
    "path": "resources/sass/custom.scss",
    "content": "/* Main title */\n.title {\n    font-size: 50px;\n}\n\n/* Carousel */\n.carousel-control {\n    background-image: none !important;\n    filter: none !important;\n    color: black !important;\n}\n\n.carousel-content {\n    display: block;\n    text-align: center;\n}\n\n/* Character attributes table */\ncaption.caption-top {\n    caption-side: top !important;\n}\n\n.table-attributes {\n    /*width: 70%;*/\n    /*margin-left: 15%;*/\n    font-size: 1.8rem;\n}\n\n.table-attributes td.circle a {\n    border-radius: 25px;\n    background-color: #337ab7;\n    /*font-weight: bold;*/\n    color: white;\n}\n\n/* Images */\n.img-race {\n    width: 80% !important;\n}\n\n.active a {\n    color: white !important;\n}\n\n/* Messages */\n.message-list-container {\n    border: 2px solid #dedede;\n    background-color: #f1f1f1;\n    border-radius: 5px;\n    padding: 10px;\n    margin: 10px 0;\n}\n\n/* Darker chat container */\n.message-list-darker {\n    border-color: #ccc;\n    background-color: #ddd;\n}\n\n/* Clear floats */\n.message-list-container::after {\n    content: \"\";\n    clear: both;\n    display: table;\n}\n\n/* Message links */\n.message-list-container a {\n    color: black !important;\n}\n\n.message-list-container a:active {\n    color: red !important;\n}\n\n/* Message avatar */\n.nav-avatar {\n    overflow: hidden;\n    height: 50px;\n}\n\n.profile-picture-wrapper {\n    height: 350px;\n    max-width: 80% !important;\n    margin-left: auto !important;\n    margin-right: auto !important;\n}\n\nimg.profile-picture {\n    display: block !important;\n    max-height: 100% !important;\n    max-width: 100% !important;\n    margin: auto !important;\n}\n\nimg.profile-picture-msg {\n    max-width: 90px;\n    width: 100%;\n}\n\nimg.profile-picture-nav {\n    max-width: 80px;\n    width: 100%;\n    height: 100%;\n}\n\n/* Message Textarea Counter */\n.chars-length {\n    display: block;\n    font-size: 12px;\n    padding: 5px 20px;\n    text-align: right;\n    position: relative;\n    width: 100%;\n}\n\n.warn {\n    background-color: firebrick;\n    color: #fff;\n}\n\n/** Online/Offline status dots */\n.dot {\n    height: 10px;\n    width: 10px;\n    background-color: #bbb;\n    border-radius: 50%;\n    display: inline-block;\n}\n\n.dot-online {\n    background-color: lightgreen;\n}\n\n.dot-offline {\n    background-color: lightgray;\n}\n\n.dot-npc {\n    opacity: 0.0;\n    filter: alpha(opacity=0); /* For IE8 and earlier */\n}\n\n/** General */\n.badge-lightpink {\n    color: #fff;\n    background-color: lightpink;\n}\n\n.badge-lightskyblue {\n    color: #fff;\n    background-color: lightskyblue;\n}\n\n.text-wrap {\n    word-wrap: break-word;\n}\n\n/** Location Navigator */\n\n.location-navigator .row {\n    /*border: 1px solid red;*/\n    height: 50px;\n}\n\n/** Specific message display */\n.messages {\n    list-style: none;\n    padding: 20px 10px 0 10px;\n    margin: 0;\n}\n\n.messages .message {\n    clear: both;\n    overflow: hidden;\n    margin-bottom: 20px;\n    transition: all 0.5s linear;\n}\n\n.messages .message.left .text_wrapper {\n    background-color: #f7ffd6;\n    margin-left: 20px;\n}\n\n.messages .message.left .text_wrapper::after, .messages .message.left .text_wrapper::before {\n    right: 100%;\n    border-right-color: #f7ffd6;\n}\n\n.messages .message.right .text_wrapper {\n    background-color: #c7eafc;\n    margin-right: 20px;\n    float: right;\n}\n\n.messages .message.right .text_wrapper::after, .messages .message.right .text_wrapper::before {\n    left: 100%;\n    border-left-color: #c7eafc;\n}\n\n.messages .message .text_wrapper {\n    padding: 20px;\n    border-radius: 6px;\n    width: calc(100% - 85px);\n    min-width: 100px;\n    position: relative;\n}\n\n.messages .message .text_wrapper::after, .messages .message .text_wrapper:before {\n    top: 18px;\n    border: solid transparent;\n    content: \" \";\n    height: 0;\n    width: 0;\n    position: absolute;\n    pointer-events: none;\n}\n\n.messages .message .text_wrapper::after {\n    border-width: 13px;\n    margin-top: 0;\n}\n\n.messages .message .text_wrapper::before {\n    border-width: 15px;\n    margin-top: -2px;\n}\n\n/** Character Equipment **/\n.equipment-item {\n    height: 150px;\n    border: 1px solid gray;\n}\n\n.inventory-item {\n    height: 110px;\n    border: 1px solid gray;\n    width: 20%;\n}\n\n.inventory-item.equipped {\n    background-color: #f7ffd6;\n}\n\n.inventory-item img, .equipment-item img {\n    display: block !important;\n    max-height: 90% !important;\n    max-width: 100% !important;\n    width: 90% !important;\n    margin-left: auto !important;\n    margin-right: auto !important;\n    margin-top: 5px !important;\n}\n\n.btn-link-thin\n{\n    margin:0 !important;\n    padding:0 !important;\n    width:100% !important;\n    font-weight: 400;\n    color: #007bff;\n    background-color: transparent;\n}\n\n.btn-xxs {\n    padding: .25rem .4rem;\n    font-size: .700rem;\n    line-height: .3;\n    border-radius: .2rem;\n}\n"
  },
  {
    "path": "resources/views/auth/login.blade.php",
    "content": "@extends('base')\n\n@section('body')\n    <div class=\"container\">\n        <div class=\"row\">\n            <div class=\"col-md-8 offset-md-2\">\n                <div class=\"card\">\n                    <div class=\"card-header\">Login</div>\n                    <div class=\"card-body\">\n                        <form class=\"\" role=\"form\" method=\"POST\" action=\"{{ route('login') }}\">\n                            {{ csrf_field() }}\n\n                            <div class=\"form-group{{ $errors->has('email') ? ' has-error' : '' }} row\">\n                                <label for=\"email\" class=\"col-lg-4 col-form-label\">E-Mail Address</label>\n\n                                <div class=\"col-lg-6\">\n                                    <input id=\"email\" type=\"email\" class=\"form-control\" name=\"email\"\n                                           value=\"{{ old('email') }}\" required autofocus>\n\n                                    @if ($errors->has('email'))\n                                        <span class=\"help-block\">\n                                        <strong>{{ $errors->first('email') }}</strong>\n                                    </span>\n                                    @endif\n                                </div>\n                            </div>\n\n                            <div class=\"form-group{{ $errors->has('password') ? ' has-error' : '' }} row\">\n                                <label for=\"password\" class=\"col-lg-4 col-form-label\">Password</label>\n\n                                <div class=\"col-lg-6\">\n                                    <input id=\"password\" type=\"password\" class=\"form-control\" name=\"password\" required>\n\n                                    @if ($errors->has('password'))\n                                        <span class=\"help-block\">\n                                            <strong>{{ $errors->first('password') }}</strong>\n                                        </span>\n                                    @endif\n                                </div>\n                            </div>\n\n                            <div class=\"form-group row\">\n                                <div class=\"col-lg-6 offset-lg-4\">\n                                    <div class=\"form-check\">\n                                        <label>\n                                            <input type=\"checkbox\" name=\"remember\" {{ old('remember') ? 'checked' : '' }}> Remember Me\n                                        </label>\n                                    </div>\n                                </div>\n                            </div>\n                            <div class=\"form-group row\">\n                                <div class=\"col-lg-8 offset-lg-4\">\n                                    <button type=\"submit\" class=\"btn btn-primary\">\n                                        Login\n                                    </button>\n\n                                    <a class=\"btn btn-link\" href=\"{{ route('password.request') }}\">\n                                        Forgot Your Password?\n                                    </a>\n                                </div>\n                            </div>\n                        </form>\n                    </div>\n                </div>\n            </div>\n        </div>\n    </div>\n@endsection\n"
  },
  {
    "path": "resources/views/auth/passwords/email.blade.php",
    "content": "@extends('base')\n\n@section('body')\n<div class=\"container\">\n    <div class=\"row\">\n        <div class=\"col-md-8 offset-md-2\">\n            <div class=\"card\">\n                <div class=\"card-header\">Reset Password</div>\n\n                <div class=\"card-body\">\n\n                    <form class=\"form-horizontal\" role=\"form\" method=\"POST\" action=\"{{ route('password.email') }}\">\n                        {{ csrf_field() }}\n\n                        <div class=\"form-group{{ $errors->has('email') ? ' has-error' : '' }} row\">\n                            <label for=\"email\" class=\"col-lg-4 col-form-label\">E-Mail Address</label>\n\n                            <div class=\"col-md-6\">\n                                <input id=\"email\" type=\"email\" class=\"form-control\" name=\"email\" value=\"{{ old('email') }}\" required>\n\n                                @if ($errors->has('email'))\n                                    <span class=\"help-block\">\n                                        <strong>{{ $errors->first('email') }}</strong>\n                                    </span>\n                                @endif\n                            </div>\n                        </div>\n\n                        <div class=\"form-group row\">\n                            <div class=\"col-lg-6 offset-lg-4\">\n                                <button type=\"submit\" class=\"btn btn-primary\">\n                                    Send Password Reset Link\n                                </button>\n                            </div>\n                        </div>\n                    </form>\n                </div>\n            </div>\n        </div>\n    </div>\n</div>\n@endsection\n"
  },
  {
    "path": "resources/views/auth/passwords/reset.blade.php",
    "content": "@extends('base')\n\n@section('body')\n<div class=\"container\">\n    <div class=\"row\">\n        <div class=\"col-md-8 offset-md-2\">\n            <div class=\"card\">\n                <div class=\"card-header\">Reset Password</div>\n\n                <div class=\"card-body\">\n\n                    <form class=\"form-horizontal\" role=\"form\" method=\"POST\" action=\"{{ route('password.request') }}\">\n                        {{ csrf_field() }}\n\n                        <input type=\"hidden\" name=\"token\" value=\"{{ $token }}\">\n\n                        <div class=\"form-group{{ $errors->has('email') ? ' has-error' : '' }} row\">\n                            <label for=\"email\" class=\"col-md-4 control-label\">E-Mail Address</label>\n\n                            <div class=\"col-md-6\">\n                                <input id=\"email\" type=\"email\" class=\"form-control\" name=\"email\" value=\"{{ $email ?? old('email') }}\" required autofocus>\n\n                                @if ($errors->has('email'))\n                                    <span class=\"help-block\">\n                                        <strong>{{ $errors->first('email') }}</strong>\n                                    </span>\n                                @endif\n                            </div>\n                        </div>\n\n                        <div class=\"form-group{{ $errors->has('password') ? ' has-error' : '' }} row\">\n                            <label for=\"password\" class=\"col-md-4 control-label\">Password</label>\n\n                            <div class=\"col-md-6\">\n                                <input id=\"password\" type=\"password\" class=\"form-control\" name=\"password\" required>\n\n                                @if ($errors->has('password'))\n                                    <span class=\"help-block\">\n                                        <strong>{{ $errors->first('password') }}</strong>\n                                    </span>\n                                @endif\n                            </div>\n                        </div>\n\n                        <div class=\"form-group{{ $errors->has('password_confirmation') ? ' has-error' : '' }} row\">\n                            <label for=\"password-confirm\" class=\"col-md-4 control-label\">Confirm Password</label>\n                            <div class=\"col-md-6\">\n                                <input id=\"password-confirm\" type=\"password\" class=\"form-control\" name=\"password_confirmation\" required>\n\n                                @if ($errors->has('password_confirmation'))\n                                    <span class=\"help-block\">\n                                        <strong>{{ $errors->first('password_confirmation') }}</strong>\n                                    </span>\n                                @endif\n                            </div>\n                        </div>\n\n                        <div class=\"form-group row\">\n                            <div class=\"col-lg-6 offset-lg-4\">\n                                <button type=\"submit\" class=\"btn btn-primary\">\n                                    Reset Password\n                                </button>\n                            </div>\n                        </div>\n                    </form>\n                </div>\n            </div>\n        </div>\n    </div>\n</div>\n@endsection\n"
  },
  {
    "path": "resources/views/auth/register.blade.php",
    "content": "@extends('base')\n\n@section('body')\n    <div class=\"container\">\n        <div class=\"row\">\n            <div class=\"col-md-8 offset-md-2\">\n                <div class=\"card\">\n                    <div class=\"card-header\">Register</div>\n                    <div class=\"card-body\">\n                        <form class=\"\" role=\"form\" method=\"POST\" action=\"{{ route('register') }}\">\n                            {{ csrf_field() }}\n\n                            <div class=\"form-group{{ $errors->has('name') ? ' has-error' : '' }} row\">\n                                <label for=\"name\" class=\"col-lg-4 col-form-label\">Name</label>\n\n                                <div class=\"col-lg-6\">\n                                    <input id=\"name\" type=\"text\" class=\"form-control\" name=\"name\" value=\"{{ old('name') }}\" required autofocus>\n\n                                    @if ($errors->has('name'))\n                                        <span class=\"help-block\">\n                                        <strong>{{ $errors->first('name') }}</strong>\n                                    </span>\n                                    @endif\n                                </div>\n                            </div>\n\n                            <div class=\"form-group{{ $errors->has('email') ? ' has-error' : '' }} row\">\n                                <label for=\"email\" class=\"col-lg-4 col-form-label\">E-Mail Address</label>\n\n                                <div class=\"col-lg-6\">\n                                    <input id=\"email\" type=\"email\" class=\"form-control\" name=\"email\" value=\"{{ old('email') }}\" required>\n\n                                    @if ($errors->has('email'))\n                                        <span class=\"help-block\">\n                                        <strong>{{ $errors->first('email') }}</strong>\n                                    </span>\n                                    @endif\n                                </div>\n                            </div>\n\n                            <div class=\"form-group{{ $errors->has('password') ? ' has-error' : '' }} row\">\n                                <label for=\"password\" class=\"col-lg-4 col-form-label\">Password</label>\n                                <div class=\"col-lg-6\">\n                                    <input id=\"password\" type=\"password\" class=\"form-control\" name=\"password\" required>\n\n                                    @if ($errors->has('password'))\n                                        <span class=\"help-block\">\n                                        <strong>{{ $errors->first('password') }}</strong>\n                                    </span>\n                                    @endif\n                                </div>\n                            </div>\n\n                            <div class=\"form-group row\">\n                                <label for=\"password-confirm\" class=\"col-lg-4 col-form-label\">Confirm Password</label>\n                                <div class=\"col-lg-6\">\n                                    <input id=\"password-confirm\" type=\"password\" class=\"form-control\" name=\"password_confirmation\"\n                                           required>\n                                </div>\n                            </div>\n                            <div class=\"form-group row\">\n                                <div class=\"col-lg-6 offset-md-4\">\n                                    <button type=\"submit\" class=\"btn btn-primary\">Register</button>\n                                </div>\n                            </div>\n                        </form>\n                    </div>\n                </div>\n            </div>\n        </div>\n    </div>\n@endsection\n"
  },
  {
    "path": "resources/views/base.blade.php",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    @section('head')\n        <meta charset=\"utf-8\">\n        <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n        <meta name=\"google\" content=\"notranslate\">\n        <meta name=\"csrf-token\" content=\"{{ csrf_token() }}\">\n        <script>\n            window.Laravel = { csrfToken: '{{ csrf_token() }}' };\n\n            window._asset = '{{ asset('') }}';\n        </script>\n        {{--<meta http-equiv=\"refresh\" content=\"30\">--}}\n        <link rel=\"stylesheet\" href=\"{{ asset('css/app.css') }}\">\n    @show\n</head>\n<body>\n\n<div class=\"container\" id=\"app\">\n    @include('partials.navbar')\n\n    @include('partials.flash-messages')\n\n    @yield('body')\n</div>\n\n@section('footer')\n    <script src=\"{{ asset('js/app.js') }}\"></script>\n@show\n</body>\n</html>\n"
  },
  {
    "path": "resources/views/battle/partials/no-battles.blade.php",
    "content": "<div class=\"message-list-container row\">\n    <div class=\"col-md-12 text-center\">\n        No battles.\n    </div>\n</div>"
  },
  {
    "path": "resources/views/battle/show.blade.php",
    "content": "@extends(\"base\")\n\n@section(\"head\")\n    <title>{{ $battle->location->name }}</title>\n    @parent\n@stop\n\n@section(\"body\")\n\n    <div class=\"row\">\n\n        <div class=\"col-lg-6\">\n            <h2>Participants</h2>\n            <hr>\n\n            <ul class=\"list-group\">\n                <li class=\"list-group-item\">\n                    <a href=\"{{ route('character.show', ['character' => $battle->getAttacker()]) }}\">\n                    {{$battle->attacker->name}} (Attacker)\n                    </a>\n                </li>\n                <li class=\"list-group-item\">\n                    <a href=\"{{ route('character.show', ['character' => $battle->getDefender()]) }}\">\n                    {{$battle->defender->name}} (Defender)\n                    </a>\n                </li>\n                <li class=\"list-group-item\">\n                    The winner is: {{$battle->victor->name}}\n                </li>\n                <li class=\"list-group-item\">\n                    The winner XP gained: {{$battle->victor_xp_gained}}\n                </li>\n            </ul>\n            <hr>\n\n            <a href=\"{{ route('index') }}\">\n                Back\n                <span class=\"fa fa-history\"></span>\n            </a>\n        </div>\n\n        <div class=\"col-lg-6\">\n            <h2>Battle log:</h2>\n            <hr>\n            <ul class=\"list-group\">\n                @foreach($battle->rounds as $index => $round)\n                    <li class=\"list-group-item\">\n                        <h3>Round {{$index + 1}}</h3>\n                        <ul class=\"list-group\">\n                            @foreach($round->turns as $index => $turn)\n                                @switch($turn->result_type)\n                                    @case('miss')\n                                        <li class=\"list-group-item\">\n                                            {{ $turn->executor->name }} was unable to hit {{ $turn->target->name }}.\n                                        </li>\n                                        @break\n\n                                    @case('hit')\n                                        <li class=\"list-group-item {{ $index % 2 ? 'text-primary' : 'text-success'}}\">\n                                            {{ $turn->executor->name }} did <b>{{ $turn->damageDone }}</b> damage\n                                            to {{ $turn->target->name }}.\n                                            @if($turn->damageAbsorbed)\n                                                <br>\n                                                <span class=\"text-secondary\">\n                                                    <b>{{ $turn->damageAbsorbed }}</b> damage was absorbed by\n                                                    {{ $turn->target->name }}'s armor.\n                                                </span>\n                                            @endif\n                                        </li>\n                                        @break\n\n                                    @case('critical_hit')\n                                        <li class=\"list-group-item text-danger\">\n                                            {{ $turn->executor->name }} did <b>{{ $turn->damageDone }}</b> critical damage\n                                            to {{ $turn->target->name }}.\n                                            @if($turn->damageAbsorbed)\n                                                <br>\n                                                <span class=\"text-secondary\">\n                                                    <b>{{ $turn->damageAbsorbed }}</b> damage was absorbed by\n                                                    {{ $turn->target->name }}'s armor.\n                                                </span>\n                                            @endif\n                                        </li>\n                                        @break\n\n                                    @default\n                                        Something went wrong ...\n                                @endswitch\n                            @endforeach\n                        </ul>\n                    </li>\n                @endforeach\n            </ul>\n        </div>\n\n    </div>\n\n@stop\n"
  },
  {
    "path": "resources/views/character/battle/index.blade.php",
    "content": "@extends(\"base\")\n\n@section(\"head\")\n    <title>{{ $character->name }} battles</title>\n    @parent\n@stop\n\n@section(\"body\")\n\n    <div class=\"row\">\n        <div class=\"col-md-10 offset-md-1\">\n            <h2 class=\"text-center\">{{ $character->name }}'s battles</h2>\n            <ul class=\"list-group\">\n                @forelse ($battles as $battle)\n                    <li class=\"list-group-item text-center\">\n                        <a class=\"d-block mx-1 h-100\" href=\"{{ route('battle.show', compact('battle')) }}\">\n                            <div class=\"row\">\n                                <div class=\"col-md-2\">\n                                    <small>{{ $battle->created_at->diffForHumans() }}</small>\n                                </div>\n                                <div class=\"col-md-8\">\n                                    @component('components.short_character_description', ['character' => $battle->getAttacker()])\n                                    @endcomponent\n                                    <span class=\"fas fa-long-arrow-alt-right text-danger\"></span>\n                                    @component('components.short_character_description', ['character' => $battle->getDefender()])\n                                    @endcomponent\n                                </div>\n                                <div class=\"col-md-2\">\n                                    @if($battle->isTheVictor($character))\n                                        <span class=\"fas fa-check text-success\"> victory</span>\n                                    @else\n                                        <span class=\"fas fa-times text-danger\"> loss</span>\n                                    @endif\n                                </div>\n                            </div>\n                        </a>\n                    </li>\n                @empty\n                    @include('battle.partials.no-battles')\n                @endforelse\n                {{ $battles->links() }}\n            </ul>\n        </div>\n    </div>\n\n@stop\n"
  },
  {
    "path": "resources/views/character/create.blade.php",
    "content": "@extends(\"base\")\n\n@section(\"head\")\n    <title>Create Character</title>\n    @parent\n@stop\n\n@section(\"body\")\n    <div class=\"row\">\n\n        <div class=\"col-lg-4 offset-lg-1 col-md-6 carousel carousel-race hidden-xsd-none d-sm-block\" data-interval=\"false\">\n            <!-- Race Image slides -->\n            <div class=\"carousel-inner\" role=\"listbox\">\n                @foreach($races as $i => $race)\n                <div class=\"carousel-item{{ ($i == 0) ? ' active' : '' }} text-center\">\n                    <img class=\"img-race img-male\" src=\"{{ asset($race->male_image) }}\">\n                    <img class=\"img-race img-female\" src=\"{{ asset($race->female_image) }}\" style=\"display: none;\">\n                    <div class=\"text-dark\">\n                        <h3>{{ $race->name }}</h3>\n                        <p>{{ $race->description }}</p>\n                    </div>\n                </div>\n                @endforeach\n            </div>\n        </div>\n\n        <div class=\"col-lg-4 offset-lg-1 col-md-6\">\n            <form role=\"form\" method=\"POST\" action=\"{{ URL::route('character.store') }}\">\n                {!! csrf_field() !!}\n                <input type=\"hidden\" name=\"race_id\" id=\"race_id\" value=\"{{ $races[0]->id }}\">\n                <input type=\"hidden\" name=\"gender\" id=\"gender\" value=\"male\">\n\n                <h3 class=\"text-center\">Create game character</h3>\n                <div class=\"form-group\">\n                    <div>\n                        <label for=\"name\" class=\"sr-only\">Name</label>\n                        <input type=\"text\" name=\"name\" value=\"{{ old('name') }}\" class=\"form-control\" placeholder=\"Name\" required=\"\" autofocus=\"\">\n                    </div>\n                </div>\n\n                <div class=\"form-group carousel carousel-race\" id=\"race-carousel\" data-interval=\"false\">\n\n                    <!-- Race Name slides -->\n                    <div class=\"carousel-inner text-center\" role=\"listbox\">\n                        @foreach($races as $i => $race)\n\n                        <div class=\"carousel-item{{ ($i == 0) ? ' active' : '' }}\" id=\"race-id-{{ $race->id }}\">\n                                <h3>{{ $race->name }}</h3>\n                        </div>\n\n                        @endforeach\n                    </div>\n\n                    <!-- Left and right controls -->\n                    <a class=\"left-race carousel-control-prev text-dark\" href=\"#race-carousel\" role=\"button\">\n                        <span class=\"fa fa-chevron-left\" aria-hidden=\"true\"></span>\n                        <span class=\"sr-only\">Previous</span>\n                    </a>\n                    <a class=\"right-race carousel-control-next text-dark\" href=\"#race-carousel\" role=\"button\">\n                        <span class=\"fa fa-chevron-right\" aria-hidden=\"true\"></span>\n                        <span class=\"sr-only\">Next</span>\n                    </a>\n\n                </div>\n                <div class=\"form-group carousel carousel-gender\" id=\"gender-carousel\" data-interval=\"false\">\n                    <!-- Gender slides -->\n                    <div class=\"carousel-inner text-center\" role=\"listbox\">\n\n                        <div class=\"carousel-item active\" id=\"male\">\n                            <h3>Male</h3>\n                        </div>\n\n                        <div class=\"carousel-item\" id=\"female\">\n                            <h3>Female</h3>\n                        </div>\n\n                    </div>\n\n                    <a class=\"left-gender carousel-control-prev text-dark\" href=\"#gender-carousel\" role=\"button\">\n                        <span class=\"fa fa-chevron-left\" aria-hidden=\"true\"></span>\n                        <span class=\"sr-only\">Previous</span>\n                    </a>\n\n                    <a class=\"right-gender carousel-control-next text-dark\" href=\"#gender-carousel\" role=\"button\">\n                        <span class=\"fa fa-chevron-right\" aria-hidden=\"true\"></span>\n                        <span class=\"sr-only\">Next</span>\n                    </a>\n\n                </div>\n                <div class=\"form-group carousel carousel-race\" id=\"race-carousel\" data-interval=\"false\">\n                    <!-- Race Stats slides -->\n                    <div class=\"carousel-inner\" role=\"listbox\">\n                        @foreach($races as $i => $race)\n                        <div class=\"carousel-item{{ ($i == 0) ? ' active' : '' }} table-responsive table-attributes\">\n                            <table class=\"table\">\n                                <tr>\n                                    <th>Strength</th>\n                                    <td>{{ $race->strength }}</td>\n                                </tr>\n                                <tr>\n                                    <th>Agility</th>\n                                    <td>{{ $race->agility }}</td>\n                                </tr>\n                                <tr>\n                                    <th>Constitution</th>\n                                    <td>{{ $race->constitution }}</td>\n                                </tr>\n                                <tr>\n                                    <th>Intelligence</th>\n                                    <td>{{ $race->intelligence }}</td>\n                                </tr>\n                                <tr>\n                                    <th>Charisma</th>\n                                    <td>{{ $race->charisma }}</td>\n                                </tr>\n                            </table>\n                        </div>\n                        @endforeach\n                    </div>\n\n                </div>\n\n                <div>\n                    <button type=\"submit\" class=\"btn btn-success btn-block\">Create Character</button>\n                </div>\n            </form>\n        </div>\n\n    </div>\n\n@stop\n\n@section(\"footer\")\n    @parent\n\n    <script src=\"{{ asset('js/character-create.js') }}\"></script>\n@stop"
  },
  {
    "path": "resources/views/character/inventory/index.blade.php",
    "content": "@extends('base')\n\n@section('head')\n    <title>Inventory</title>\n    @parent\n@stop\n\n@section('body')\n    <div class=\"row\">\n\n        <!-- Left Side -->\n        <div class=\"col-md-6\">\n\n            <inventory-management :character=\"{{ $character->load('inventory.items') }}\"></inventory-management>\n\n        </div>\n\n\n        <!-- Right Side -->\n        <div class=\"col-md-6\">\n\n            @include('character.partials.general', compact('character', 'level'))\n\n            @include('character.partials.attributes', compact('character'))\n\n            @include('character.partials.statistics', compact('character'))\n\n        </div>\n\n    </div>\n\n@stop\n\n@section('footer')\n    @parent\n\n@stop\n"
  },
  {
    "path": "resources/views/character/message/index.blade.php",
    "content": "@extends(\"base\")\n\n@section(\"head\")\n    <title>Conversation with {{$character->name}}</title>\n    @parent\n@stop\n\n@section(\"body\")\n\n    <div class=\"col-lg-10 offset-md-1 col-md-12 mt-3\">\n\n        <div class=\"column\">\n            <form role=\"form\" method=\"POST\" action=\"{{ URL::route('character.message.store', compact('character')) }}\">\n                {!! csrf_field() !!}\n                <div class=\"form-group row\">\n                    <label for=\"content\" class=\"sr-only\">Message</label>\n                    <textarea maxlength=\"{{ $contentLimit }}\"\n                              class=\"form-control countdown\" placeholder=\"Write something to {{$character->name}} ...\"\n                              required autofocus name=\"content\"\n                              rows=\"7\"></textarea>\n                </div>\n                <div class=\"row\">\n                    <button type=\"submit\" class=\"btn btn-success btn-block\">Send</button>\n                </div>\n            </form>\n        </div>\n\n        <div class=\"column\">\n            <ul class=\"messages\">\n                @foreach ($messages as $message)\n                    @if($message->from_id === $currentCharacter->id)\n                        @include('message.partials.my-message', compact('message'))\n                    @else\n                        @include('message.partials.others-message', compact('message'))\n                    @endif\n                @endforeach\n                {{ $messages->links() }}\n            </ul>\n        </div>\n\n    </div>\n\n@stop\n\n@section(\"footer\")\n    @parent\n\n    <script src=\"{{ asset('js/vcountdown.js') }}\"></script>\n    <script>\n        VCountdown({\n            target: '.countdown',\n            maxChars: '{{ $contentLimit }}'\n        });\n    </script>\n@stop"
  },
  {
    "path": "resources/views/character/partials/actions.blade.php",
    "content": "<form role=\"form\" method=\"POST\" class=\"mx-1\">\n    {!! csrf_field() !!}\n    <div class=\"text-center mt-3\">\n        @if($character->isYou())\n            <a class=\"btn btn-sm btn-primary\" href=\"{{ route('inventory.index') }}\">\n                Inventory\n                <span class=\"fas fa-shopping-bag\"></span>\n            </a>\n            <a class=\"btn btn-sm btn-primary\" href=\"{{ route('store.index') }}\">\n                Store\n                <span class=\"fas fa-shopping-bag\"></span>\n            </a>\n        @else\n            <div class=\"mx-1 my-3 px-5 text-center\" role=\"group\" aria-label=\"Character Actions\">\n                @if($character->isPlayerCharacter())\n                    <a href=\"{{ route('character.message.index', ['character' => $character]) }}\"\n                       class=\"btn btn-sm btn-success\">\n                        message <span class=\"fa fa-comment\"></span>\n                    </a>\n                @endif\n\n                <button formaction=\"{{ route('character.attack', ['character' => $character]) }}\"\n                        class=\"btn btn-sm btn-danger\">\n                    attack <span class=\"fas fa-bolt\"></span>\n                </button>\n\n                <a href=\"{{ route('character.store.index', ['character' => $character]) }}\"\n                   class=\"btn btn-sm btn-info\">\n                    trade <span class=\"fas fa-money-bill\"></span>\n                </a>\n            </div>\n        @endif\n    </div>\n</form>\n"
  },
  {
    "path": "resources/views/character/partials/attributes.blade.php",
    "content": "<?php\n/** @var \\App\\Models\\Character $character */\n\n$hasFreePoints = ($character->isYou() && $character->available_attribute_points);\n?>\n\n@if($hasFreePoints)\n    <form role=\"form\" method=\"POST\" action=\"{{ route('character.update', $character) }}\"\n          id=\"increment_attribute\">\n        {{ method_field('PUT') }}\n        {!! csrf_field() !!}\n\n        <input type=\"hidden\" id=\"attribute_input\" name=\"attribute\" value=\"strength\">\n        @endif\n\n        <table class=\"table\">\n            <caption class=\"caption-top\">Attributes</caption>\n            <tr>\n                <th scope=\"row\">Strength</th>\n                <td>{{ $character->strength }}</td>\n                @component('components.increment_attribute_button', compact('hasFreePoints'))\n                    {{ 'strength' }}\n                @endcomponent\n            </tr>\n            <tr>\n                <th scope=\"row\">Agility</th>\n                <td>{{ $character->agility }}</td>\n                @component('components.increment_attribute_button', compact('hasFreePoints'))\n                    {{ 'agility' }}\n                @endcomponent\n            </tr>\n            <tr>\n                <th scope=\"row\">Constitution</th>\n                <td>{{ $character->constitution }}</td>\n                @component('components.increment_attribute_button', compact('hasFreePoints'))\n                    {{ 'constitution' }}\n                @endcomponent\n            </tr>\n            <tr>\n                <th scope=\"row\">Intelligence</th>\n                <td>{{ $character->intelligence }}</td>\n                @component('components.increment_attribute_button', compact('hasFreePoints'))\n                    {{ 'intelligence' }}\n                @endcomponent\n            </tr>\n            <tr>\n                <th scope=\"row\">Charisma</th>\n                <td>{{ $character->charisma }}</td>\n                @component('components.increment_attribute_button', compact('hasFreePoints'))\n                    {{ 'charisma' }}\n                @endcomponent\n            </tr>\n\n            @if($hasFreePoints)\n                <tfoot>\n                <tr>\n                    <th scope=\"row\">Available points</th>\n                    <td class=\"circle\">{{ $character->available_attribute_points }}</td>\n                </tr>\n                </tfoot>\n            @endif\n\n        </table>\n\n        @if($hasFreePoints)\n    </form>\n@endif"
  },
  {
    "path": "resources/views/character/partials/character-display.blade.php",
    "content": "@php\n    /** @var \\App\\Models\\Character $character */\n    $hpPercent = ($character->getHitPoints() / $character->getTotalHitPoints()) * 100;\n@endphp\n\n<div class=\"progress mx-5 my-3\">\n    <div class=\"progress-bar bg-danger\"\n         role=\"progressbar\"\n         style=\"width: {{ $hpPercent }}%\"\n         aria-valuenow=\"{{ $hpPercent }}\"\n         aria-valuemin=\"0\"\n         aria-valuemax=\"100\">\n        {{ $character->getHitPoints() }} / {{ $character->getTotalHitPoints() }}\n    </div>\n</div>\n\n<div class=\"profile-picture-wrapper row\">\n    <img class=\"profile-picture\" src=\"{{ asset($character->getProfilePictureFull()) }}\">\n</div>\n\n@if($character->isYou())\n    <div class=\"mx-5 my-3\">\n        <form role=\"form\" method=\"POST\"\n              action=\"{{ route('character.profile-picture.store', compact('character')) }}\"\n              enctype=\"multipart/form-data\">\n            {!! csrf_field() !!}\n            <div class=\"input-group\">\n                <div class=\"custom-file\">\n                    <input type=\"file\" name=\"file\" class=\"form-control form-control-sm\" required>\n                </div>\n                <div class=\"mx-2 input-group-append\">\n                    <button type=\"submit\" class=\"btn btn-success\">\n                        Upload <span class=\"fas fa-upload\"></span>\n                    </button>\n                </div>\n            </div>\n        </form>\n    </div>\n\n    @if($character->hasProfilePicture())\n        <div class=\"text-center\">\n            @php\n                /** @var \\App\\Models\\Character $character */\n                $profile_picture = $character->getProfilePicture();\n            @endphp\n            <form role=\"form\" method=\"POST\"\n                  action=\"{{ route('character.profile-picture.destroy', compact('character', 'profile_picture')) }}\">\n                {{ method_field('DELETE') }}\n                {!! csrf_field() !!}\n                <div class=\"mx-2\">\n                    <button type=\"submit\" class=\"btn btn-sm btn-danger\">\n                        Delete Profile Picture\n                        <span class=\"fas fa-save\"></span>\n                    </button>\n                </div>\n            </form>\n        </div>\n    @endif\n@endif\n\n"
  },
  {
    "path": "resources/views/character/partials/equipment-item-mutable.blade.php",
    "content": "@if($item)\n    <button type=\"submit\" class=\"btn btn-link-thin\"\n            formaction=\"{{ route('inventory.item.un-equip', compact('item')) }}\">\n        <img src=\"{{ asset($item->image_file_path) }}\">\n    </button>\n@endif\n"
  },
  {
    "path": "resources/views/character/partials/equipment-item.blade.php",
    "content": "@if($item)\n    <img src=\"{{ asset($item->image_file_path) }}\">\n@endif\n"
  },
  {
    "path": "resources/views/character/partials/equipment-mutable.blade.php",
    "content": "@php\n    /** @var \\App\\Models\\Character $character */\n    /** @var \\App\\Models\\Item $item */\n@endphp\n\n<form role=\"form\" method=\"POST\" class=\"mx-1\">\n    {!! csrf_field() !!}\n    <div class=\"row mx-1 table-dark align-items-center\">\n        <div class=\"col-3 equipment-item\">\n            @php\n                $item = $character->getHeadGearItem();\n            @endphp\n            Head gear\n            @include('character.partials.equipment-item-mutable', compact('item'))\n        </div>\n        <div class=\"col-3 equipment-item\">\n            @php\n                $item = $character->getBodyArmorItem();\n            @endphp\n            Body armor\n            @include('character.partials.equipment-item-mutable', compact('item'))\n        </div>\n        <div class=\"col-3 equipment-item\">\n            @php\n                $item = $character->getMainHandItem();\n            @endphp\n            Main hand\n            @include('character.partials.equipment-item-mutable', compact('item'))\n        </div>\n        <div class=\"col-3 equipment-item\">\n            @php\n                $item = $character->getOffHandItem();\n            @endphp\n            Off hand\n            @include('character.partials.equipment-item-mutable', compact('item'))\n        </div>\n    </div>\n</form>\n"
  },
  {
    "path": "resources/views/character/partials/equipment.blade.php",
    "content": "@php\n    /** @var \\App\\Models\\Character $character */\n    /** @var \\App\\Models\\Item $item */\n@endphp\n\n<div class=\"mt-5 row mx-1 table-dark align-items-center mx-1\">\n    <div class=\"col-3 equipment-item\">\n        @php\n            $item = $character->getHeadGearItem()\n        @endphp\n        Head gear\n        @include('character.partials.equipment-item', compact('item'))\n    </div>\n    <div class=\"col-3 equipment-item\">\n        @php\n            $item = $character->getBodyArmorItem()\n        @endphp\n        Body armor\n        @include('character.partials.equipment-item', compact('item'))\n    </div>\n    <div class=\"col-3 equipment-item\">\n        @php\n            $item = $character->getMainHandItem()\n        @endphp\n        Main hand\n        @include('character.partials.equipment-item', compact('item'))\n    </div>\n    <div class=\"col-3 equipment-item\">\n        @php\n            $item = $character->getOffHandItem()\n        @endphp\n        Off hand\n        @include('character.partials.equipment-item', compact('item'))\n    </div>\n</div>\n"
  },
  {
    "path": "resources/views/character/partials/general.blade.php",
    "content": "<table class=\"table\">\n    <caption class=\"caption-top\">General</caption>\n    <tr>\n        <th scope=\"row\">Race</th>\n        <td>{{ $character->getRaceName() }}</td>\n    </tr>\n    <tr>\n        <th scope=\"row\">Gender</th>\n        <td>{{ $character->gender }}</td>\n    </tr>\n    <tr>\n        <th scope=\"row\">Level</th>\n        <td>{{ $level->getId() }}</td>\n    </tr>\n    <tr>\n        <th scope=\"row\">XP</th>\n        <td>\n            <div class=\"progress\">\n                <div class=\"progress-bar\"\n                     role=\"progressbar\"\n                     style=\"width: {{ $level->getProgress($character->xp) }}%\"\n                     aria-valuenow=\"{{ $level->getProgress($character->xp) }}\"\n                     aria-valuemin=\"0\"\n                     aria-valuemax=\"100\">\n                    {{ $character->xp }} / {{ $level->getNextXpThreshold() }}\n                </div>\n            </div>\n        </td>\n    </tr>\n</table>\n"
  },
  {
    "path": "resources/views/character/partials/inventory.blade.php",
    "content": "@php\n    /** @var \\App\\Models\\Character $character */\n    /** @var \\App\\Models\\Item $item */\n    $items = $character->inventory->items;\n@endphp\n\n<form role=\"form\" method=\"POST\">\n    {!! csrf_field() !!}\n    <div class=\"my-3 row mx-1 table-dark align-items-center\">\n        @foreach(range(0, App\\Modules\\Equipment\\Domain\\Inventory::NUMBER_OF_SLOTS) as $slotNumber)\n            @php\n                $item = $items->where('pivot.inventory_slot_number', $slotNumber)->first();\n                $isHighlighted = isset($item) && $item->isEquipped() ? 'equipped' : '';\n            @endphp\n\n            <div class=\"inventory-item {{ $isHighlighted }}\">\n                @if($item)\n                    @if($item->isEquipped())\n                        <button type=\"submit\" class=\"btn btn-link-thin\"\n                                formaction=\"{{ route('inventory.item.un-equip', compact('item')) }}\">\n                            <img src=\"{{ asset($item->image_file_path) }}\">\n                        </button>\n                    @else\n                        <button type=\"submit\" class=\"btn btn-link-thin\"\n                                formaction=\"{{ route('inventory.item.equip', compact('item')) }}\">\n                            <img src=\"{{ asset($item->image_file_path) }}\">\n                        </button>\n                    @endif\n                @endif\n            </div>\n\n        @endforeach\n    </div>\n</form>\n"
  },
  {
    "path": "resources/views/character/partials/statistics.blade.php",
    "content": "<table class=\"table\">\n    <caption class=\"caption-top\">Statistics</caption>\n    <tr>\n        <th scope=\"row\">Reputation</th>\n        <td>{{ $character->reputation }}</td>\n    </tr>\n    <tr>\n        <th scope=\"row\">Money</th>\n        <td>{{ $character->inventory->money }}</td>\n    </tr>\n    <tr>\n        <th scope=\"row\">\n            <a href=\"{{ route('character.battle.index', compact('character')) }}\">\n                Battles Won\n            </a>\n        </th>\n        <td>{{ $character->battles_won }}</td>\n    </tr>\n    <tr>\n        <th scope=\"row\">\n            <a href=\"{{ route('character.battle.index', compact('character')) }}\">\n                Battles Lost\n            </a></th>\n        <td>{{ $character->battles_lost }}</td>\n    </tr>\n</table>\n"
  },
  {
    "path": "resources/views/character/show.blade.php",
    "content": "@extends('base')\n\n@section('head')\n    <title>{{ $character->getName() }} (Level: {{ $character->getLevelNumber() }})</title>\n    @parent\n@stop\n\n@section('body')\n    <div class=\"row\">\n\n        <div class=\"col-md-12\">\n            <h5 class=\"text-center\">\n                {{ $character->getName() }}\n            </h5>\n        </div>\n\n        <!-- Left Side -->\n        <div class=\"col-md-6\">\n\n            @include('character.partials.character-display', compact('character'))\n\n            @include('character.partials.equipment', compact('character'))\n\n            @include('character.partials.actions', compact('character'))\n\n        </div>\n\n\n        <!-- Right Side -->\n        <div class=\"col-md-6\">\n\n            @include('character.partials.general', compact('character'))\n\n            @include('character.partials.attributes', compact('character'))\n\n            @include('character.partials.statistics', compact('character'))\n\n        </div>\n    </div>\n\n@stop\n\n@section('footer')\n    @parent\n\n    <script src=\"{{ asset('js/character-update.js') }}\"></script>\n@stop\n"
  },
  {
    "path": "resources/views/components/increment_attribute_button.blade.php",
    "content": "@if($hasFreePoints)\n<td class=\"circle\">\n    <button type=\"submit\" class=\"btn btn-sm btn-success btn-block increment_attribute\" id=\"{{$slot}}\">+1</button>\n</td>\n@endif"
  },
  {
    "path": "resources/views/components/short_character_description.blade.php",
    "content": "{{ $character->name }}\n({{ $character->getRaceName() }})\n"
  },
  {
    "path": "resources/views/emails/password.blade.php",
    "content": "Click here to reset your password: {{ url('password/reset/'.$token) }}"
  },
  {
    "path": "resources/views/errors/503.blade.php",
    "content": "@extends(\"base\")\n\n@section(\"head\")\n    <title>Be right back.</title>\n\n    @parent\n@stop\n\n@section(\"body\")\n    <div class=\"content\">\n        <div class=\"title\">Be right back.</div>\n    </div>\n@stop\n"
  },
  {
    "path": "resources/views/location/partials/list-character.blade.php",
    "content": "<?php\n/** @var \\App\\Models\\Character $character * */\n$class = 'list-group-item-warning';\n\nif (!$character->isNPC()) {\n    $class = $character->isYou() ? 'active' : '';\n}\n\n?>\n\n<li class=\"list-group-item {{ $class }}\">\n\n    @if($character->isNPC())\n        <span class=\"dot dot-npc\">\n        </span>\n    @elseif($character->isOnline())\n        <span class=\"dot dot-online\">\n        </span>\n    @else\n        <span class=\"dot dot-offline\">\n        </span>\n    @endif\n\n    @if($character->gender === 'male')\n        <span class=\"badge badge-pill badge-lightskyblue\">\n            <span class=\"fa fa-mars\"></span>\n        </span>\n    @else\n        <span class=\"badge badge-pill badge-lightpink\">\n            <span class=\"fa fa-venus\"></span>\n        </span>\n    @endif\n\n    <a href=\"{{ route('character.show', ['character' => $character]) }}\">\n        @component('components.short_character_description', compact('character'))\n        @endcomponent\n    </a>\n\n    @if(!$character->isYou())\n        <span class=\"float-right\">\n            @if(!$character->isNPC())\n                <a href=\"{{ route('character.message.index', ['character' => $character]) }}\"\n                   class=\"btn btn-xxs btn-success\">\n                    message <span class=\"fa fa-comment\"></span>\n                </a>\n            @endif\n\n            @if($character->isMerchant())\n                <a href=\"{{ route('character.store.index', ['character' => $character]) }}\"\n                   class=\"btn btn-xxs btn-info\">\n                    trade <span class=\"fas fa-money-bill\"></span>\n                </a>\n            @endif\n\n            <button formaction=\"{{ route('character.attack', ['character' => $character]) }}\"\n                    class=\"btn btn-xxs btn-danger\">\n                attack <span class=\"fas fa-bolt\"></span>\n            </button>\n\n        </span>\n    @endif\n\n</li>\n"
  },
  {
    "path": "resources/views/location/partials/navigator.blade.php",
    "content": "@php\n    /** @var \\App\\Models\\Character $character */\n    $character = Auth::user()->character;\n@endphp\n\n<form role=\"form\" method=\"POST\" class=\"mx-1\">\n    {!! csrf_field() !!}\n    <div class=\"row mx-1 location-navigator mt-5 mb-5\">\n        <div class=\"col\">\n            <div class=\"row\">\n                <div class=\"col\"></div>\n                <div class=\"col text-center my-auto\">\n                    @if(!is_null($adjacent = $location->adjacent('north')))\n                        <div>\n                            <button type=\"submit\"\n                                    class=\"btn btn-link\"\n                                    formaction=\"{{ route('character.move', ['character' => $character, 'location' => $location->adjacent('north')]) }}\">\n                                {{ $location->adjacent('north')->name }}\n                            </button>\n                        </div>\n                        <span class=\"fa fa-angle-up\"></span>\n                    @endif\n                </div>\n                <div class=\"col\"></div>\n            </div>\n\n            <div class=\"row\">\n            </div>\n\n            <div class=\"row\">\n                <div class=\"col text-right my-auto\">\n                    @if(!is_null($adjacent = $location->adjacent('west')))\n                        <div>\n                            <button type=\"submit\"\n                                    class=\"btn btn-link\"\n                                    formaction=\"{{ route('character.move', ['character' => $character, 'location' => $location->adjacent('west')]) }}\">\n                                {{ $location->adjacent('west')->name }}\n                            </button>\n                            <span class=\"fa fa-angle-left\"></span>\n                        </div>\n                    @endif\n                </div>\n                <div class=\"col text-center my-auto\"><span class=\"fas fa-walking fa-2x\"></span></div>\n                <div class=\"col text-left my-auto\">\n                    @if(!is_null($adjacent = $location->adjacent('east')))\n                        <div>\n                            <span class=\"fa fa-angle-right\"></span>\n                            <button type=\"submit\"\n                                    class=\"btn btn-link\"\n                                    formaction=\"{{ route('character.move', ['character' => $character, 'location' => $location->adjacent('east')]) }}\">\n                                {{ $location->adjacent('east')->name }}\n                            </button>\n                        </div>\n                    @endif\n                </div>\n            </div>\n\n            <div class=\"row\">\n            </div>\n\n            <div class=\"row\">\n                <div class=\"col\"></div>\n                <div class=\"col text-center my-auto\">\n                    @if(!is_null($adjacent = $location->adjacent('south')))\n                        <span class=\"fa fa-angle-down\"></span>\n                        <div>\n                            <button type=\"submit\"\n                                    class=\"btn btn-link\"\n                                    formaction=\"{{ route('character.move', ['character' => $character, 'location' => $location->adjacent('south')]) }}\">\n                                {{ $location->adjacent('south')->name }}\n                            </button>\n                        </div>\n                    @endif\n                </div>\n                <div class=\"col\"></div>\n            </div>\n\n        </div>\n\n    </div>\n</form>\n"
  },
  {
    "path": "resources/views/location/show.blade.php",
    "content": "@extends('base')\n\n@section('head')\n    <title>{{ $location->name }}</title>\n    @parent\n@stop\n\n@section('body')\n\n    <div class=\"row mx-1\">\n        <div class=\"col-lg-6\">\n            <h5 class=\"text-center\">{{ $location->name }}</h5>\n            <hr>\n            <p>{{ $location->description }}</p>\n            <div class=\"row justify-content-center\">\n                <div class=\"col-md-8\">\n                    <img class=\"img-fluid\" src=\"{{ asset('images/'.$location->image) }}\">\n                </div>\n            </div>\n\n            @include('location.partials.navigator', compact('location'))\n\n        </div>\n\n        <div class=\"col-lg-6\">\n            <h5 class=\"text-center\">Local characters:</h5>\n            <hr>\n            <form role=\"form\" method=\"POST\" class=\"mx-1\">\n                {!! csrf_field() !!}\n                <ul class=\"list-group\">\n\n                    {!! csrf_field() !!}\n                    @foreach($location->characters as $character)\n                        @include('location.partials.list-character', compact('character'))\n                    @endforeach\n                </ul>\n            </form>\n        </div>\n    </div>\n\n@stop\n"
  },
  {
    "path": "resources/views/message/index.blade.php",
    "content": "@extends(\"base\")\n\n@section(\"head\")\n    <title>Inbox</title>\n    @parent\n@stop\n\n@section(\"body\")\n\n    <div class=\"col-lg-10 offset-md-1 col-md-12 mt-3\">\n        <div>\n            <ul class=\"messages\">\n                @forelse ($messages as $message)\n                    @php\n                        list($otherCharacter, $side) = ($message->sender->id === $currentCharacter->id)\n                            ? [$message->recipient, 'left']\n                            : [$message->sender, 'right'];\n                    @endphp\n                    @include('message.partials.conversation', compact(\n                        'message',\n                        'currentCharacter',\n                        'otherCharacter',\n                        'side'\n                    ))\n                @empty\n                    @include('message.partials.no-messages')\n                @endforelse\n                {{ $messages->links() }}\n            </ul>\n        </div>\n    </div>\n\n@stop"
  },
  {
    "path": "resources/views/message/partials/conversation-card.blade.php",
    "content": "<div>\n    <a href=\"{{ route('character.show', ['character' => $character]) }}\">\n        <div>\n            <small>\n                {{ $character->name }}\n            </small>\n        </div>\n        <div>\n            <img class=\"profile-picture-msg\" src=\"{{ asset($character->getProfilePictureSmall()) }}\" alt=\"Avatar\">\n        </div>\n    </a>\n    <div>\n        <small>\n            {{ $message->created_at->diffForHumans() }}\n        </small>\n    </div>\n</div>"
  },
  {
    "path": "resources/views/message/partials/conversation-message.blade.php",
    "content": "<a class=\"d-block mx-1 h-100\"\n       href=\"{{ route('character.message.index', ['character' => $otherCharacter->id]) }}\">\n        <div class=\"text_wrapper\">\n            <p class=\"text-wrap\">{!! $message->content !!}</p>\n        </div>\n</a>\n"
  },
  {
    "path": "resources/views/message/partials/conversation.blade.php",
    "content": "<div class=\"message-list-container row mx-1 message {{$side}}\">\n    <div class=\"col-md-2 text-center\">\n        @include('message.partials.conversation-card', ['character' => $currentCharacter, 'message' => $message])\n    </div>\n    <div class=\"col-sm-8\">\n        @include('message.partials.conversation-message', ['character' => $otherCharacter->id, 'message' => $message])\n    </div>\n    <div class=\"col-md-2 text-center\">\n        @include('message.partials.conversation-card', ['character' => $otherCharacter, 'message' => $message])\n    </div>\n</div>\n"
  },
  {
    "path": "resources/views/message/partials/my-message.blade.php",
    "content": "<div class=\"message-list-container row mx-1 message left\">\n    <div class=\"col-sm-2 text-center\">\n        @include('message.partials.conversation-card', ['character' => $message->sender, 'message' => $message])\n    </div>\n    <div class=\"col-sm-10\">\n        <div class=\"text_wrapper\">\n            <p class=\"text-wrap\">{!! $message->content !!}</p>\n        </div>\n    </div>\n</div>\n"
  },
  {
    "path": "resources/views/message/partials/no-messages.blade.php",
    "content": "<div class=\"message-list-container row\">\n    <div class=\"col-md-12 text-center\">\n        No messages.\n    </div>\n</div>"
  },
  {
    "path": "resources/views/message/partials/others-message.blade.php",
    "content": "<div class=\"message-list-container row mx-1 message right\">\n    <div class=\"col-sm-10\">\n        <div class=\"text_wrapper\">\n            <p class=\"text-wrap\">{!! $message->content !!}</p>\n        </div>\n    </div>\n    <div class=\"col-sm-2 text-center\">\n        @include('message.partials.conversation-card', ['character' => $message->sender, 'message' => $message])\n    </div>\n</div>\n"
  },
  {
    "path": "resources/views/pages/index.blade.php",
    "content": "@extends(\"base\")\n\n@section('head')\n    <title>{{ config('app.name') }}</title>\n\n    @parent\n\n@stop\n\n@section(\"body\")\n    <div class=\"row justify-content-center\">\n        <div class=\"col-lg-6\">\n\n            <img class=\"img-fluid mt-2\" src=\"{{ asset('images/village.png') }}\">\n\n            <p class=\"text-center title\">{{ config('app.name') }}</p>\n\n            <div class=\"btn-group d-flex\" role=\"group\">\n                <a href=\"{{ URL::route('register') }}\" class=\"btn btn-success w-100\">Register</a>\n                <a href=\"{{ URL::route('login') }}\" class=\"btn btn-primary w-100\">Login</a>\n            </div>\n\n        </div>\n    </div>\n@stop\n"
  },
  {
    "path": "resources/views/partials/flash-messages.blade.php",
    "content": "@php\n    /** @var \\Illuminate\\Support\\ViewErrorBag $errors */\n\n    $messages = [];\n    foreach ($errors->all() as $error) {\n        $messages[] = [\n            'text' => $error,\n            'type' => 'error',\n        ];\n    }\n\n    if (session('status')) {\n        $messages[] = [\n            'text' => session('status'),\n            'type' => 'success',\n        ];\n    }\n\n@endphp\n\n<flash-messages :messages=\"{{ json_encode($messages) }}\"></flash-messages>"
  },
  {
    "path": "resources/views/partials/navbar.blade.php",
    "content": "<nav class=\"navbar navbar-light bg-light navbar-expand-md\">\n    <button type=\"button\" class=\"navbar-toggler\" data-toggle=\"collapse\" data-target=\"#myNavbar\">&#x2630;\n    </button>\n    <a class=\"navbar-brand\" href=\"{{ URL::route('home') }}\">{{ config('app.name') }}</a>\n\n\n    <div class=\"collapse navbar-collapse\" id=\"myNavbar\">\n        <ul class=\"nav navbar-nav\">\n            @if (Auth::check() && Auth::user()->hasCharacter())\n                <li class=\"nav-item button\">\n                    <a href=\"{{ route('character.show', ['character' => Auth::user()->character]) }}\" class=\"nav-link\">\n                        <span class=\"fa fa-user-circle\" aria-hidden=\"true\">\n                            Character\n                        </span>\n                    </a>\n                </li>\n                <li class=\"nav-item button\">\n                    <a href=\"{{ route('location.show', ['location' => Auth::user()->character->location]) }}\" class=\"nav-link\">\n                        <span class=\"fa fa-university\" aria-hidden=\"true\">\n                            Location\n                        </span>\n                    </a>\n                </li>\n                <li class=\"nav-item button\">\n                    <a href=\"{{ URL::route('message.index') }}\" class=\"nav-link\">\n                        <span class=\"fa fa-envelope\">\n                            Messages\n                            @if(Auth::user()->character->receivedMessages()->unread()->count() > 0)\n                                <span class=\"badge badge-danger\">\n                                     {{ Auth::user()->character->receivedMessages()->unread()->count() }}\n                                </span>\n                            @endif\n                        </span>\n                    </a>\n                </li>\n                <li class=\"nav-item button\">\n                    <a href=\"{{ URL::route('character.battle.index', ['character' => Auth::user()->character]) }}\" class=\"nav-link\">\n                        <span class=\"fas fa-bolt\">\n                            Battles\n                            @if(Auth::user()->character->defends()->unseenByDefender()->count() > 0)\n                                <span class=\"badge badge-danger\">\n                                     {{ Auth::user()->character->defends()->unseenByDefender()->count() }}\n                                </span>\n                            @endif\n                        </span>\n                    </a>\n                </li>\n                @if (Auth::user()->hasPermission('browse_admin'))\n                    <li class=\"nav-item button\">\n                        <a href=\"{{ URL::route('voyager.dashboard') }}\" class=\"nav-link\">\n                        <span class=\"fas fa-tachometer-alt\">\n                            Admin\n                        </span>\n                        </a>\n                    </li>\n                @endif\n            @endif\n        </ul>\n        <ul class=\"nav navbar-nav ml-auto\">\n            @if (Auth::check())\n                @if (Auth::user()->hasCharacter() && Auth::user()->character->hasProfilePicture())\n                    <li class=\"nav-item nav-avatar d-flex\">\n                        <a class=\"align-self-baseline\" href=\"{{ route('character.show', ['character' => Auth::user()->character]) }}\">\n                            <img class=\"profile-picture-nav\"\n                                 src=\"{{ asset(Auth::user()->character->getProfilePictureSmall()) }}\"\n                                 alt=\"Avatar\">\n                        </a>\n                    </li>\n                @endif\n                <li class=\"nav-item\">\n                    <a href=\"#\" class=\"nav-link\">\n                        <form role=\"form\" method=\"POST\" action=\"{{ route('logout') }}\">\n                            {{ csrf_field() }}\n                            <button type=\"submit\"><span class=\"glyphicon glyphicon-log-out\"></span> Logout</button>\n                        </form>\n                    </a>\n                </li>\n            @else\n                <li class=\"nav-item\">\n                    <a href=\"{{ URL::route('register') }}\" class=\"nav-link\">\n                            <span class=\"glyphicon glyphicon-user\">\n                            </span> Register\n                    </a>\n                </li>\n                <li class=\"nav-item\">\n                    <a href=\"{{ URL::route('login') }}\" class=\"nav-link\">\n                            <span class=\"glyphicon glyphicon-log-in\">\n                            </span> Login\n                    </a>\n                </li>\n            @endif\n        </ul>\n    </div>\n</nav>\n"
  },
  {
    "path": "resources/views/trade/own_store/index.blade.php",
    "content": "@extends('base')\n\n@section('head')\n    <title>Store</title>\n    @parent\n@stop\n\n@section('body')\n\n    <store-management :character=\"{{ $character->load('inventory.items', 'store.items') }}\"></store-management>\n\n    <div class=\"row\">\n\n        <!-- Left Side -->\n        <div class=\"col-md-6\">\n\n            <div class=\"text-center my-3\">\n                <a class=\"btn btn-sm btn-primary\" href=\"{{  route('character.show',  compact('character')) }}\">\n                    Back to Profile\n                    <span class=\"fa fa-arrow-left\"></span>\n                </a>\n            </div>\n\n        </div>\n\n        <!-- Right Side -->\n        <div class=\"col-md-6\">\n        </div>\n\n    </div>\n\n@stop\n\n@section('footer')\n    @parent\n\n@stop\n"
  },
  {
    "path": "resources/views/trade/store/index.blade.php",
    "content": "@extends('base')\n\n@section('head')\n    <title>Store</title>\n    @parent\n@stop\n\n@section('body')\n\n    <store-trade :customer=\"{{ $customer->load('inventory.items.prototype') }}\" :trader=\"{{ $trader->load('store.items.prototype') }}\"></store-trade>\n\n    <div class=\"row\">\n\n        <!-- Left Side -->\n        <div class=\"col-md-6\">\n        </div>\n\n        <!-- Right Side -->\n        <div class=\"col-md-6\">\n        </div>\n\n    </div>\n\n@stop\n\n@section('footer')\n    @parent\n\n@stop\n"
  },
  {
    "path": "resources/views/vendor/.gitkeep",
    "content": ""
  },
  {
    "path": "resources/views/vendor/pagination/bootstrap-4.blade.php",
    "content": "@if ($paginator->hasPages())\n    <ul class=\"pagination\">\n        {{-- Previous Page Link --}}\n        @if ($paginator->onFirstPage())\n            <li class=\"page-item disabled\"><span class=\"page-link\">&laquo;</span></li>\n        @else\n            <li class=\"page-item\"><a class=\"page-link\" href=\"{{ $paginator->previousPageUrl() }}\" rel=\"prev\">&laquo;</a></li>\n        @endif\n\n        {{-- Pagination Elements --}}\n        @foreach ($elements as $element)\n            {{-- \"Three Dots\" Separator --}}\n            @if (is_string($element))\n                <li class=\"page-item disabled\"><span class=\"page-link\">{{ $element }}</span></li>\n            @endif\n\n            {{-- Array Of Links --}}\n            @if (is_array($element))\n                @foreach ($element as $page => $url)\n                    @if ($page == $paginator->currentPage())\n                        <li class=\"page-item active\"><span class=\"page-link\">{{ $page }}</span></li>\n                    @else\n                        <li class=\"page-item\"><a class=\"page-link\" href=\"{{ $url }}\">{{ $page }}</a></li>\n                    @endif\n                @endforeach\n            @endif\n        @endforeach\n\n        {{-- Next Page Link --}}\n        @if ($paginator->hasMorePages())\n            <li class=\"page-item\"><a class=\"page-link\" href=\"{{ $paginator->nextPageUrl() }}\" rel=\"next\">&raquo;</a></li>\n        @else\n            <li class=\"page-item disabled\"><span class=\"page-link\">&raquo;</span></li>\n        @endif\n    </ul>\n@endif\n"
  },
  {
    "path": "resources/views/vendor/pagination/default.blade.php",
    "content": "@if ($paginator->hasPages())\n    <ul class=\"pagination\">\n        {{-- Previous Page Link --}}\n        @if ($paginator->onFirstPage())\n            <li class=\"page-item disabled\"><span class=\"page-link\">&laquo;</span></li>\n        @else\n            <li class=\"page-item\"><a class=\"page-link\" href=\"{{ $paginator->previousPageUrl() }}\" rel=\"prev\">&laquo;</a></li>\n        @endif\n\n        {{-- Pagination Elements --}}\n        @foreach ($elements as $element)\n            {{-- \"Three Dots\" Separator --}}\n            @if (is_string($element))\n                <li class=\"page-item disabled\"><span class=\"page-link\">{{ $element }}</span></li>\n            @endif\n\n            {{-- Array Of Links --}}\n            @if (is_array($element))\n                @foreach ($element as $page => $url)\n                    @if ($page == $paginator->currentPage())\n                        <li class=\"page-item active\"><span class=\"page-link\">{{ $page }}</span></li>\n                    @else\n                        <li class=\"page-item\"><a class=\"page-link\" href=\"{{ $url }}\">{{ $page }}</a></li>\n                    @endif\n                @endforeach\n            @endif\n        @endforeach\n\n        {{-- Next Page Link --}}\n        @if ($paginator->hasMorePages())\n            <li class=\"page-item\"><a class=\"page-link\" href=\"{{ $paginator->nextPageUrl() }}\" rel=\"next\">&raquo;</a></li>\n        @else\n            <li class=\"page-item disabled\"><span class=\"page-link\">&raquo;</span></li>\n        @endif\n    </ul>\n@endif\n"
  },
  {
    "path": "resources/views/vendor/pagination/semantic-ui.blade.php",
    "content": "@if ($paginator->hasPages())\n    <div class=\"ui pagination menu\">\n        {{-- Previous Page Link --}}\n        @if ($paginator->onFirstPage())\n            <a class=\"icon item disabled\"> <i class=\"left chevron icon\"></i> </a>\n        @else\n            <a class=\"icon item\" href=\"{{ $paginator->previousPageUrl() }}\" rel=\"prev\"> <i class=\"left chevron icon\"></i> </a>\n        @endif\n\n        {{-- Pagination Elements --}}\n        @foreach ($elements as $element)\n            {{-- \"Three Dots\" Separator --}}\n            @if (is_string($element))\n                <a class=\"icon item disabled\">{{ $element }}</a>\n            @endif\n\n            {{-- Array Of Links --}}\n            @if (is_array($element))\n                @foreach ($element as $page => $url)\n                    @if ($page == $paginator->currentPage())\n                        <a class=\"item active\" href=\"{{ $url }}\">{{ $page }}</a>\n                    @else\n                        <a class=\"item\" href=\"{{ $url }}\">{{ $page }}</a>\n                    @endif\n                @endforeach\n            @endif\n        @endforeach\n\n        {{-- Next Page Link --}}\n        @if ($paginator->hasMorePages())\n            <a class=\"icon item\" href=\"{{ $paginator->nextPageUrl() }}\" rel=\"next\"> <i class=\"right chevron icon\"></i> </a>\n        @else\n            <a class=\"icon item disabled\"> <i class=\"right chevron icon\"></i> </a>\n        @endif\n    </div>\n@endif\n"
  },
  {
    "path": "resources/views/vendor/pagination/simple-bootstrap-4.blade.php",
    "content": "@if ($paginator->hasPages())\n    <ul class=\"pagination\">\n        {{-- Previous Page Link --}}\n        @if ($paginator->onFirstPage())\n            <li class=\"page-item disabled\"><span class=\"page-link\">@lang('pagination.previous')</span></li>\n        @else\n            <li class=\"page-item\"><a class=\"page-link\" href=\"{{ $paginator->previousPageUrl() }}\" rel=\"prev\">@lang('pagination.previous')</a></li>\n        @endif\n\n        {{-- Next Page Link --}}\n        @if ($paginator->hasMorePages())\n            <li class=\"page-item\"><a class=\"page-link\" href=\"{{ $paginator->nextPageUrl() }}\" rel=\"next\">@lang('pagination.next')</a></li>\n        @else\n            <li class=\"page-item disabled\"><span class=\"page-link\">@lang('pagination.next')</span></li>\n        @endif\n    </ul>\n@endif\n"
  },
  {
    "path": "resources/views/vendor/pagination/simple-default.blade.php",
    "content": "@if ($paginator->hasPages())\n    <ul class=\"pagination\">\n        {{-- Previous Page Link --}}\n        @if ($paginator->onFirstPage())\n            <li class=\"disabled\"><span>@lang('pagination.previous')</span></li>\n        @else\n            <li><a href=\"{{ $paginator->previousPageUrl() }}\" rel=\"prev\">@lang('pagination.previous')</a></li>\n        @endif\n\n        {{-- Next Page Link --}}\n        @if ($paginator->hasMorePages())\n            <li><a href=\"{{ $paginator->nextPageUrl() }}\" rel=\"next\">@lang('pagination.next')</a></li>\n        @else\n            <li class=\"disabled\"><span>@lang('pagination.next')</span></li>\n        @endif\n    </ul>\n@endif\n"
  },
  {
    "path": "routes/api.php",
    "content": "<?php\n\nuse Illuminate\\Http\\Request;\nuse Illuminate\\Support\\Facades\\Route;\n\n/*\n|--------------------------------------------------------------------------\n| API Routes\n|--------------------------------------------------------------------------\n|\n| Here is where you can register API routes for your application. These\n| routes are loaded by the RouteServiceProvider within a group which\n| is assigned the \"api\" middleware group. Enjoy building your API!\n|\n*/\n\nRoute::middleware('auth:api')->get('/user', function (Request $request) {\n    return $request->user();\n});"
  },
  {
    "path": "routes/channels.php",
    "content": "<?php\n\nuse Illuminate\\Support\\Facades\\Broadcast;\n\n/*\n|--------------------------------------------------------------------------\n| Broadcast Channels\n|--------------------------------------------------------------------------\n|\n| Here you may register all of the event broadcasting channels that your\n| application supports. The given channel authorization callbacks are\n| used to check if an authenticated user can listen to the channel.\n|\n*/\n\nBroadcast::channel('App.Models.User.{id}', function ($user, $id) {\n    return (int) $user->id === (int) $id;\n});\n"
  },
  {
    "path": "routes/console.php",
    "content": "<?php\n\nuse Illuminate\\Foundation\\Inspiring;\nuse Illuminate\\Support\\Facades\\Artisan;\n\n/*\n|--------------------------------------------------------------------------\n| Console Routes\n|--------------------------------------------------------------------------\n|\n| This file is where you may define all of your Closure based console\n| commands. Each Closure is bound to a command instance allowing a\n| simple approach to interacting with each command's IO methods.\n|\n*/\n\nArtisan::command('inspire', function () {\n    $this->comment(Inspiring::quote());\n})->describe('Display an inspiring quote');\n"
  },
  {
    "path": "routes/web.php",
    "content": "<?php\n\nuse Illuminate\\Support\\Facades\\Auth;\nuse Illuminate\\Support\\Facades\\Route;\nuse TCG\\Voyager\\Facades\\Voyager;\n\n/*\n|--------------------------------------------------------------------------\n| Web Routes\n|--------------------------------------------------------------------------\n|\n| Here is where you can register web routes for your application. These\n| routes are loaded by the RouteServiceProvider within a group which\n| contains the \"web\" middleware group. Now create something great!\n|\n*/\n\n// Route models...\nRoute::post('/character/{character}/location/{location}/move', 'CharacterController@move')->name('character.move');\nRoute::post('/character/{character}/attack', 'CharacterController@attack')->name('character.attack');\nRoute::post('/inventory/item/{item}/equip', 'InventoryController@equipItem')->name('inventory.item.equip');\nRoute::post('/inventory/item/{item}/un-equip', 'InventoryController@unEquipItem')->name('inventory.item.un-equip');\n\n// Simple routes...\nRoute::group(['middleware' => 'guest'], static function () {\n    Route::get('/', static function () {\n        return view('pages.index');\n    })->name('index');\n});\n\nRoute::group(['middleware' => ['auth', 'has.character']], static function () {\n    Route::get('/home', static function () {\n        $location = Auth::user()->character->location;\n        return redirect()->route('location.show', compact('location'));\n    })->name('home');\n});\n\nAuth::routes();\n\n// Route resources...\nRoute::resource('inventory', 'InventoryController')->only('index');\nRoute::resource('store', 'OwnStoreController')->only('index');\nRoute::resource('character', 'CharacterController')->only('create', 'store', 'show', 'update');\nRoute::resource('location', 'LocationController')->only(['show']);\nRoute::resource('battle', 'BattleController')->only(['show']);\nRoute::resource('message', 'MessageController')->only(['index']);\nRoute::resource('character.message', 'CharacterMessageController')->only(['index', 'store']);\nRoute::resource('character.store', 'CharacterStoreController')->only(['index']);\nRoute::resource('character.profile-picture', 'ProfilePictureController')->only(['store', 'destroy']);\nRoute::resource('character.battle', 'CharacterBattleController')->only(['index']);\n\n\nRoute::group(['prefix' => 'admin'], static function () {\n    Voyager::routes();\n});\n\nRoute::middleware(['auth', 'has.character'])->namespace('Api')->prefix('api')->group(static function () {\n\n    // Manage inventory\n    Route::post('/inventory/item/{item}/equip', 'ManageInventoryController@equipItem')->name('inventory.item.equip');\n    Route::post('/inventory/item/{item}/un-equip', 'ManageInventoryController@unEquipItem')->name('inventory.item.un-equip');\n\n    // Manage store\n    Route::post('/inventory/item/{item}/move-to-store', 'ManageStoreController@moveItemToStore')->name('inventory.item.move-to-store');\n    Route::post('/store/item/{item}/change-price', 'ManageStoreController@changeItemPrice')->name('store.item.change-price');\n    Route::post('/store/item/{item}/move-to-inventory', 'ManageStoreController@moveItemToInventory')->name('store.item.move-to-inventory');\n    Route::post('/inventory/money/move-to-store', 'ManageStoreController@moveMoneyToStore')->name('inventory.money.move-to-store');\n    Route::post('/store/money/move-to-inventory', 'ManageStoreController@moveMoneyToInventory')->name('store.money.move-to-inventory');\n\n    // Trade\n    Route::post('/store/{store}/item/{item}/buy', 'TradeController@buyItem')->name('store.item.buy');\n    Route::post('/store/{store}/item/{item}/sell', 'TradeController@sellItem')->name('store.item.sell');\n});\n"
  },
  {
    "path": "scheduler.bat",
    "content": "cd %~dp0%\nphp artisan schedule:run 1>> NUL 2>&1\n"
  },
  {
    "path": "server.php",
    "content": "<?php\n\n/**\n * Laravel - A PHP Framework For Web Artisans\n *\n * @package  Laravel\n * @author   Taylor Otwell <taylor@laravel.com>\n */\n\n$uri = urldecode(\n    parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH)\n);\n\n// This file allows us to emulate Apache's \"mod_rewrite\" functionality from the\n// built-in PHP web server. This provides a convenient way to test a Laravel\n// application without having installed a \"real\" web server software here.\nif ($uri !== '/' && file_exists(__DIR__.'/public'.$uri)) {\n    return false;\n}\n\nrequire_once __DIR__.'/public/index.php';\n"
  },
  {
    "path": "storage/app/public/.gitignore",
    "content": "*\n!.gitignore\n"
  },
  {
    "path": "storage/debugbar/.gitignore",
    "content": "*\n!.gitignore\n"
  },
  {
    "path": "storage/framework/.gitignore",
    "content": "compiled.php\nconfig.php\ndown\nevents.scanned.php\nmaintenance.php\nroutes.php\nroutes.scanned.php\nschedule-*\nservices.json"
  },
  {
    "path": "storage/framework/cache/.gitignore",
    "content": "*\n!data/\n!.gitignore\n"
  },
  {
    "path": "storage/framework/sessions/.gitignore",
    "content": "*\n!.gitignore\n"
  },
  {
    "path": "storage/framework/testing/.gitignore",
    "content": "*\n!.gitignore\n"
  },
  {
    "path": "storage/framework/views/.gitignore",
    "content": "*\n!.gitignore\n"
  },
  {
    "path": "storage/logs/.gitignore",
    "content": "*\n!.gitignore\n"
  },
  {
    "path": "tests/Browser/ExampleTest.php",
    "content": "<?php\n\nnamespace Tests\\Browser;\n\nuse Tests\\DuskTestCase;\nuse Laravel\\Dusk\\Browser;\nuse Throwable;\n\nclass ExampleTest extends DuskTestCase\n{\n    /**\n     * A basic browser test example.\n     *\n     * @return void\n     *\n     * @throws Throwable\n     */\n    public function testBasicExample()\n    {\n        $this->browse(function (Browser $browser) {\n            $browser->visit('/')\n                    ->assertSee(config('app.name'));\n        });\n    }\n}\n"
  },
  {
    "path": "tests/Browser/Pages/HomePage.php",
    "content": "<?php\n\nnamespace Tests\\Browser\\Pages;\n\nuse Laravel\\Dusk\\Browser;\n\nclass HomePage extends Page\n{\n    /**\n     * Get the URL for the page.\n     *\n     * @return string\n     */\n    public function url()\n    {\n        return '/';\n    }\n\n    /**\n     * Assert that the browser is on the page.\n     *\n     * @param  Browser  $browser\n     * @return void\n     */\n    public function assert(Browser $browser)\n    {\n        //\n    }\n\n    /**\n     * Get the element shortcuts for the page.\n     *\n     * @return array\n     */\n    public function elements()\n    {\n        return [\n            '@element' => '#selector',\n        ];\n    }\n}\n"
  },
  {
    "path": "tests/Browser/Pages/Page.php",
    "content": "<?php\n\nnamespace Tests\\Browser\\Pages;\n\nuse Laravel\\Dusk\\Page as BasePage;\n\nabstract class Page extends BasePage\n{\n    /**\n     * Get the global element shortcuts for the site.\n     *\n     * @return array\n     */\n    public static function siteElements()\n    {\n        return [\n            '@element' => '#selector',\n        ];\n    }\n}\n"
  },
  {
    "path": "tests/Browser/console/.gitignore",
    "content": "*\n!.gitignore\n"
  },
  {
    "path": "tests/Browser/screenshots/.gitignore",
    "content": "*\n!.gitignore\n"
  },
  {
    "path": "tests/CreatesApplication.php",
    "content": "<?php\n\nnamespace Tests;\n\nuse Illuminate\\Contracts\\Console\\Kernel;\n\ntrait CreatesApplication\n{\n    /**\n     * Creates the application.\n     *\n     * @return \\Illuminate\\Foundation\\Application\n     */\n    public function createApplication()\n    {\n        $app = require __DIR__.'/../bootstrap/app.php';\n\n        $app->make(Kernel::class)->bootstrap();\n\n        return $app;\n    }\n}\n"
  },
  {
    "path": "tests/DuskTestCase.php",
    "content": "<?php\n\nnamespace Tests;\n\nuse Laravel\\Dusk\\TestCase as BaseTestCase;\nuse Facebook\\WebDriver\\Chrome\\ChromeOptions;\nuse Facebook\\WebDriver\\Remote\\RemoteWebDriver;\nuse Facebook\\WebDriver\\Remote\\DesiredCapabilities;\n\nabstract class DuskTestCase extends BaseTestCase\n{\n    use CreatesApplication;\n\n    /**\n     * Prepare for Dusk test execution.\n     *\n     * @beforeClass\n     * @return void\n     */\n    public static function prepare()\n    {\n        static::startChromeDriver();\n    }\n\n    /**\n     * Create the RemoteWebDriver instance.\n     *\n     * @return \\Facebook\\WebDriver\\Remote\\RemoteWebDriver\n     */\n    protected function driver()\n    {\n        $options = (new ChromeOptions)->addArguments([\n            '--disable-gpu',\n            '--headless'\n        ]);\n\n        return RemoteWebDriver::create(\n            'http://localhost:9515', DesiredCapabilities::chrome()->setCapability(\n                ChromeOptions::CAPABILITY, $options\n            )\n        );\n    }\n}\n"
  },
  {
    "path": "tests/Feature/AttackTest.php",
    "content": "<?php\n\nnamespace Tests\\Feature;\n\nuse App\\Models\\Battle;\nuse App\\Models\\Character;\nuse App\\Models\\User;\nuse Illuminate\\Foundation\\Testing\\RefreshDatabase;\nuse Tests\\TestCase;\n\nclass AttackTest extends TestCase\n{\n    use RefreshDatabase;\n\n    /**\n     * @test\n     */\n    public function strong_own_character_wins_while_attacking_basic_opponent(): void\n    {\n        // Given we have a signed in user that already has a strongCharacter\n        $user = factory(User::class)->create();\n        $this->actingAs($user);\n        /** @var Character $strongOwnCharacter */\n        $strongOwnCharacter = factory(Character::class)->create([\n            'user_id' => $user,\n            'hit_points' => 1000,\n            'strength' => 1000,\n            'agility' => 1000,\n            'constitution' => 1000,\n            'intelligence' => 1000,\n            'charisma' => 1000,\n        ]);\n        $basicOpponentCharacter = factory(Character::class)->create([\n            'location_id' => $strongOwnCharacter->location_id\n        ]);\n\n        // When we hit home folder\n        $response = $this->post(\"/character/{$basicOpponentCharacter->id}/attack\");\n\n        $battle = Battle::query()->firstOrFail();\n\n        // We are redirected to the Battle page\n        $response->assertRedirect(route('battle.show', $battle->id));\n        $this->assertEquals($strongOwnCharacter->id, $battle->attacker_id);\n        $this->assertEquals($strongOwnCharacter->id, $battle->victor_id);\n        $this->assertEquals($basicOpponentCharacter->id, $battle->defender_id);\n    }\n\n    /**\n     * @test\n     */\n    public function basic_own_character_looses_while_attacking_strong_opponent(): void\n    {\n        // Given we have a signed in user that already has a strongCharacter\n        $user = factory(User::class)->create();\n        $this->actingAs($user);\n        /** @var Character $basicOwnCharacter */\n        $basicOwnCharacter = factory(Character::class)->create([\n            'user_id' => $user,\n        ]);\n        $strongOpponentCharacter = factory(Character::class)->create([\n            'location_id' => $basicOwnCharacter->location_id,\n            'hit_points' => 1000,\n            'strength' => 1000,\n            'agility' => 1000,\n            'constitution' => 1000,\n            'intelligence' => 1000,\n            'charisma' => 1000,\n        ]);\n\n        // When we hit home folder\n        $response = $this->post(\"/character/{$strongOpponentCharacter->id}/attack\");\n\n        $battle = Battle::query()->firstOrFail();\n\n        // We are redirected to the Battle page\n        $response->assertRedirect(route('battle.show', $battle->id));\n        $this->assertEquals($basicOwnCharacter->id, $battle->attacker_id);\n        $this->assertEquals($strongOpponentCharacter->id, $battle->victor_id);\n        $this->assertEquals($strongOpponentCharacter->id, $battle->defender_id);\n    }\n}\n"
  },
  {
    "path": "tests/Feature/CharacterCreationTest.php",
    "content": "<?php\n\nnamespace Tests\\Feature;\n\nuse App\\Models\\Character;\nuse App\\Models\\User;\nuse Illuminate\\Foundation\\Testing\\RefreshDatabase;\nuse Tests\\TestCase;\nuse Illuminate\\Foundation\\Testing\\WithoutMiddleware;\nuse Illuminate\\Foundation\\Testing\\DatabaseMigrations;\nuse Illuminate\\Foundation\\Testing\\DatabaseTransactions;\n\nclass CharacterCreationTest extends TestCase\n{\n    use RefreshDatabase;\n\n    /**\n     * @test\n     */\n    public function an_authenticated_user_without_character_record_is_redirected_to_character_create_page()\n    {\n        // Given we have a signed in user that does not have character yet\n        $user = factory(User::class)->create();\n        $this->actingAs($user);\n\n        // When we hit home folder\n        $response = $this->get('/home');\n\n        // We are redirected to the Character creation page\n        $response->assertRedirect(route('character.create'));\n    }\n\n    /**\n     * @test\n     */\n    public function an_authenticated_user_with_character_record_is_redirected_to_character_location_page()\n    {\n        // Given we have a signed in user that already has a character\n        $user = factory(User::class)->create();\n        $this->actingAs($user);\n        $character = factory(Character::class)->create(['user_id' => $user]);\n\n        // When we hit home folder\n        $response = $this->get('/home');\n\n        // We are redirected to the Character creation page\n        $response->assertRedirect(route('location.show', $character->location));\n    }\n}\n"
  },
  {
    "path": "tests/Feature/ExampleTest.php",
    "content": "<?php\n\nnamespace Tests\\Feature;\n\nuse Tests\\TestCase;\nuse Illuminate\\Foundation\\Testing\\RefreshDatabase;\n\nclass ExampleTest extends TestCase\n{\n    /**\n     * A basic test example.\n     *\n     * @return void\n     */\n    public function test_example()\n    {\n        $response = $this->get('/');\n\n        $response->assertStatus(200);\n    }\n}\n"
  },
  {
    "path": "tests/TestCase.php",
    "content": "<?php\n\nnamespace Tests;\n\nuse Illuminate\\Foundation\\Testing\\TestCase as BaseTestCase;\n\nabstract class TestCase extends BaseTestCase\n{\n    use CreatesApplication;\n}\n"
  },
  {
    "path": "tests/Unit/ExampleTest.php",
    "content": "<?php\n\nnamespace Tests\\Unit;\n\nuse Tests\\TestCase;\n\nclass ExampleTest extends TestCase\n{\n    /**\n     * A basic test example.\n     *\n     * @return void\n     */\n    public function test_example()\n    {\n        self::assertTrue(true);\n    }\n}\n"
  },
  {
    "path": "tests/Unit/app/Modules/Equipment/Application/Services/ItemServiceTest.php",
    "content": "<?php\n\nnamespace Tests\\Unit\\App\\Modules\\Equipment\\Application\\Services;\n\nuse App\\Modules\\Character\\Application\\Contracts\\CharacterRepositoryInterface;\nuse App\\Modules\\Character\\Domain\\Character;\nuse App\\Modules\\Character\\Domain\\CharacterId;\nuse App\\Modules\\Equipment\\Application\\Commands\\CreateItemCommand;\nuse App\\Modules\\Equipment\\Application\\Contracts\\ItemPrototypeRepositoryInterface;\nuse App\\Modules\\Equipment\\Application\\Contracts\\ItemRepositoryInterface;\nuse App\\Modules\\Equipment\\Domain\\Item;\nuse App\\Modules\\Equipment\\Domain\\ItemId;\nuse App\\Modules\\Equipment\\Domain\\ItemPrice;\nuse App\\Modules\\Equipment\\Domain\\ItemPrototype;\nuse App\\Modules\\Equipment\\Application\\Factories\\ItemFactory;\nuse App\\Modules\\Equipment\\Application\\Services\\ItemService;\nuse App\\Modules\\Equipment\\Domain\\ItemEffect;\nuse App\\Modules\\Equipment\\Domain\\ItemPrototypeId;\nuse App\\Modules\\Equipment\\Domain\\ItemType;\nuse Illuminate\\Support\\Collection;\nuse Mockery;\nuse Mockery\\MockInterface;\nuse PHPUnit\\Framework\\Assert;\nuse Tests\\TestCase;\n\nclass ItemServiceTest extends TestCase\n{\n    /** @var ItemService */\n    private $sut;\n\n    /** @var MockInterface| CharacterRepositoryInterface */\n    private $characterRepository;\n\n    /** @var MockInterface| ItemRepositoryInterface */\n    private $itemRepository;\n\n    /** @var MockInterface| ItemPrototypeRepositoryInterface */\n    private $itemPrototypeRepository;\n\n    /** @var MockInterface| Character */\n    private $character;\n\n    protected function setUp(): void\n    {\n        parent::setUp();\n\n        $this->characterRepository = Mockery::mock(CharacterRepositoryInterface::class);\n        $this->itemRepository = Mockery::mock(ItemRepositoryInterface::class);\n        $this->itemPrototypeRepository = Mockery::mock(ItemPrototypeRepositoryInterface::class);\n        $this->character = Mockery::mock(Character::class);\n\n        $this->sut = new ItemService(\n            $this->characterRepository,\n            $this->itemRepository,\n            $this->itemPrototypeRepository,\n            new ItemFactory()\n        );\n    }\n\n    public function testCreate(): void\n    {\n        // Arrange\n        $itemId = ItemId::fromString('598d1570-e0e3-40d1-979b-64e48626f777');\n        $itemPrototypeId = ItemPrototypeId::fromString('598d1570-e0e3-40d1-979b-64e48626f6f6');\n        $name = 'Wooden club';\n        $description = 'Club made from wood';\n        $type = ItemType::mainHand();\n        $price = ItemPrice::ofAmount(30);\n        $effects = Collection::make([\n            ItemEffect::damage(5)\n        ]);\n        $creatorCharacterId = CharacterId::fromString('65976e46-d2eb-4373-ba69-b7c9ea81b56f');\n        $imageFilePath = 'images\\equipment\\main_hand\\1club.png';\n\n        $itemPrototype = new ItemPrototype(\n            $itemPrototypeId,\n            $name,\n            $description,\n            $imageFilePath,\n            $type,\n            $effects,\n            $price\n        );\n\n        $createCommand = new CreateItemCommand($itemPrototypeId, $creatorCharacterId);\n\n        $this->characterRepository->shouldReceive('getOne')->once()->andReturn($this->character);\n        $this->itemPrototypeRepository->shouldReceive('getOne')->once()->andReturn($itemPrototype);\n        $this->itemRepository->shouldReceive('nextIdentity')->once()->andReturn($itemId);\n        $this->character->shouldReceive('getId')->once()->andReturn($creatorCharacterId);\n        $this->character->shouldReceive('addItemToInventory')->once();\n        $this->itemRepository->shouldReceive('add')->once()\n            ->with(\\Mockery::on(static function (Item $item)\n            use ($itemId, $name, $description, $imageFilePath, $type, $effects, $itemPrototypeId, $creatorCharacterId, $price) {\n\n                // Assert\n                Assert::assertEquals($itemId, $item->getId());\n                Assert::assertEquals($name, $item->getName());\n                Assert::assertEquals($description, $item->getDescription());\n                Assert::assertEquals($imageFilePath, $item->getImageFilePath());\n                Assert::assertEquals($type, $item->getType());\n                Assert::assertEquals($effects, $item->getEffects());\n                Assert::assertEquals($itemPrototypeId, $item->getPrototypeId());\n                Assert::assertEquals($creatorCharacterId, $item->getCreatorCharacterId());\n                Assert::assertEquals($price, $item->getPrice());\n\n                return true;\n            }));\n        $this->characterRepository->shouldReceive('update')->once();\n\n        // Act\n        $this->sut->create($createCommand);\n    }\n}\n"
  },
  {
    "path": "tests/Unit/app/Modules/Equipment/Domain/InventoryTest.php",
    "content": "<?php declare(strict_types=1);\n\n\nnamespace Tests\\Unit\\app\\Modules\\Equipment\\Domain;\n\nuse App\\Modules\\Character\\Domain\\CharacterId;\nuse App\\Modules\\Equipment\\Domain\\Inventory;\nuse App\\Modules\\Equipment\\Domain\\InventoryId;\nuse App\\Modules\\Equipment\\Domain\\InventoryItem;\nuse App\\Modules\\Equipment\\Domain\\Item;\nuse App\\Modules\\Equipment\\Domain\\ItemStatus;\nuse App\\Modules\\Equipment\\Domain\\Money;\nuse App\\Modules\\Generic\\Domain\\Container\\NotEnoughSpaceInContainerException;\nuse Illuminate\\Support\\Collection;\nuse InvalidArgumentException;\nuse Mockery;\nuse Tests\\TestCase;\n\nclass InventoryTest extends TestCase\n{\n    /** @var InventoryId */\n    private $id;\n\n    /** @var CharacterId */\n    private $characterId;\n\n    /** @var Money */\n    private $money;\n\n    protected function setUp(): void\n    {\n        parent::setUp();\n\n        $this->id = Mockery::mock(InventoryId::class);\n        $this->characterId = Mockery::mock(CharacterId::class);\n        $this->money = Mockery::mock(Money::class);\n    }\n\n    public function testWillThrowExceptionOnTryingToCreateInventoryWithNonInventoryItems(): void\n    {\n        $this->expectException(InvalidArgumentException::class);\n\n        new Inventory(\n            $this->id,\n            $this->characterId,\n            Collection::make([\n                Mockery::mock(Item::class),\n            ]),\n            $this->money\n        );\n    }\n\n    public function testWillThrowExceptionOnTryingToCreateInventoryWithTooManyItems(): void\n    {\n        $items = $this->generateItems(Inventory::NUMBER_OF_SLOTS + 1);\n\n        $this->expectException(NotEnoughSpaceInContainerException::class);\n\n        new Inventory(\n            $this->id,\n            $this->characterId,\n            $items,\n            $this->money\n        );\n    }\n\n    public function testCreatingNewInventoryWithMaximumNumberOfItemsWorks(): void\n    {\n        $numberOfSlots = Inventory::NUMBER_OF_SLOTS;\n\n        $items = $this->generateItems($numberOfSlots);\n\n        $sut = new Inventory(\n            $this->id,\n            $this->characterId,\n            $items,\n            $this->money\n        );\n\n        $this->assertSame($numberOfSlots, $sut->getItems()->count());\n    }\n\n    public function testCreatingNewInventoryWithNoItemsWorks(): void\n    {\n        $sut = new Inventory(\n            $this->id,\n            $this->characterId,\n            new Collection(),\n            $this->money\n        );\n\n        $this->assertSame(0, $sut->getItems()->count());\n    }\n\n    public function testRightAmountOfMoneyAfterPuttingMoneyIn(): void\n    {\n        $initialMoney = new Money(5);\n\n        $sut = new Inventory(\n            $this->id,\n            $this->characterId,\n            $this->generateItems(5),\n            $initialMoney\n        );\n\n        $this->assertSame(\n            $initialMoney->getValue(),\n            $sut->getMoney()->getValue()\n        );\n    }\n\n    public function testRightAmountOfMoneyAfterPuttingMoreMoneyIn(): void\n    {\n        $initialMoney = new Money(5);\n        $additionalMoney = new Money(4);\n\n        $sut = new Inventory(\n            $this->id,\n            $this->characterId,\n            $this->generateItems(5),\n            $initialMoney\n        );\n\n        $sut->putMoneyIn($additionalMoney);\n\n        $this->assertSame(\n            $initialMoney->getValue() + $additionalMoney->getValue(),\n            $sut->getMoney()->getValue()\n        );\n    }\n\n    public function testRightAmountOfMoneyAfterTakingMoneyOut(): void\n    {\n        $initialMoney = new Money(5);\n        $moneyToTakeOut = new Money(4);\n\n        $sut = new Inventory(\n            $this->id,\n            $this->characterId,\n            $this->generateItems(5),\n            $initialMoney\n        );\n\n        $sut->takeMoneyOut($moneyToTakeOut);\n\n        $this->assertSame(\n            $initialMoney->getValue() - $moneyToTakeOut->getValue(),\n            $sut->getMoney()->getValue()\n        );\n    }\n\n    public function testAddingItemSequentially(): void\n    {\n        $initialNumberOfItems = $additionalItemOffset = 5;\n        $additionalItem = Mockery::mock(Item::class);\n\n        $sut = new Inventory(\n            $this->id,\n            $this->characterId,\n            $this->generateItems($initialNumberOfItems),\n            $this->money\n        );\n\n        $additionalItem->shouldReceive('getId')->atLeast()->once();\n        $additionalItem->shouldReceive('getName')->atLeast()->once();\n        $additionalItem->shouldReceive('getDescription')->atLeast()->once();\n        $additionalItem->shouldReceive('getImageFilePath')->atLeast()->once();\n        $additionalItem->shouldReceive('getType')->atLeast()->once();\n        $additionalItem->shouldReceive('getEffects')->atLeast()->once();\n        $additionalItem->shouldReceive('getPrice')->atLeast()->once();\n        $additionalItem->shouldReceive('getPrototypeId')->atLeast()->once();\n        $additionalItem->shouldReceive('getCreatorCharacterId')->atLeast()->once();\n\n        $sut->add($additionalItem);\n\n        $this->assertSame($initialNumberOfItems + 1, $sut->getItems()->count());\n        $this->assertEquals(\n            new InventoryItem($additionalItem, ItemStatus::inBackpack()),\n            $sut->getItems()->offsetGet($additionalItemOffset)\n        );\n    }\n\n    private function generateItems(int $numberOfItems): Collection\n    {\n        return Collection::make(array_map(static function () {\n\n            return Mockery::mock(InventoryItem::class);\n\n        }, range(0, $numberOfItems - 1)));\n    }\n}\n"
  },
  {
    "path": "tests/Unit/app/Modules/Level/Application/Services/LevelServiceTest.php",
    "content": "<?php\n\n\nnamespace Tests\\Unit\\App\\Modules\\Level\\Application\\Services;\n\nuse App\\Modules\\Level\\Domain\\Level;\nuse App\\Modules\\Level\\Application\\Services\\LevelService;\nuse Tests\\TestCase;\n\nclass LevelServiceTest extends TestCase\n{\n    /** @var LevelService */\n    private $levelService;\n\n    protected function setUp():void\n    {\n        parent::setUp();\n\n        $this->levelService = new LevelService();\n    }\n\n    public function xpForLevelServiceProvider()\n    {\n        $levels = (new LevelService())->getLevels(10);\n\n        $levelMiddlePoints = array_map(static function (Level $level) {\n            $middlePoint = floor(($level->getCurrentXpThreshold() + $level->getNextXpThreshold()) / 2);\n\n            return [\n                'xp' => (int)$middlePoint,\n                'levelId' => $level->getId(),\n            ];\n\n        }, $levels);\n\n        return $levelMiddlePoints;\n    }\n\n    /**\n     * @dataProvider xpForLevelServiceProvider\n     *\n     * @param int $xp\n     * @param int $levelId\n     */\n    public function testGetLevelByXp(int $xp, int $levelId): void\n    {\n        $level = $this->levelService->getLevelByXp($xp);\n\n        $this->assertEquals($levelId, $level->getId());\n    }\n}\n"
  },
  {
    "path": "tests/Unit/app/Modules/Level/Domain/Entities/LevelTest.php",
    "content": "<?php\n\n\nnamespace Tests\\Unit\\App\\Modules\\Level\\Domain\\Entities;\n\nuse App\\Modules\\Level\\Domain\\Level;\nuse Tests\\TestCase;\n\nclass LevelTest extends TestCase\n{\n    public function testGetProgress()\n    {\n        $level = new Level(1, 50, 100);\n\n        $progress = $level->getProgress(75);\n\n        $this->assertEquals(50, $progress);\n    }\n\n    public function testGetProgressWithXpNotInRange()\n    {\n        $level = new Level(1, 50, 100);\n\n        $progress = $level->getProgress(5);\n\n        $this->assertEquals(0, $progress);\n    }\n}\n"
  },
  {
    "path": "webpack.mix.js",
    "content": "const mix = require('laravel-mix');\n\n/*\n |--------------------------------------------------------------------------\n | Mix Asset Management\n |--------------------------------------------------------------------------\n |\n | Mix provides a clean, fluent API for defining some Webpack build steps\n | for your Laravel application. By default, we are compiling the Sass\n | file for the application as well as bundling up all the JS files.\n |\n */\n\nmix.js('resources/js/app.js', 'public/js')\n    .vue()\n    .sass('resources/sass/app.scss', 'public/css');\n"
  }
]