احمد شش سالش است و در حال یادگیری زبان انگلیسی است. اولین چیزی که او باید یاد بگیرد، الفبای زبان انگلیسی است. به همین خاطر، سؤالهای زیادی از برادرش میپرسد. چون برادر او کارهای زیادی دارد که باید انجام دهد، از شما بهعنوان یک برنامهنویس درخواست کرده است که برای او برنامهای بنویسید که اشتباهات احمد را به او بگوید.
# جزئیات پروژه
تابعی با نام `missingLetter` پیادهسازی کنید که آرایهای از حروف انگلیسی را دریافت و حرف جا افتاده از این دنباله را برگرداند.
امضای این تابع بهصورت زیر است:
```php
function missingLetter($arr)
{
// TODO: Implement
}
```
به مثال زیر دقت نمایید:
```
missingLetter(["t", "u", "v", "w", "x", "z"]) ➞ "y"
```
# نکات
+ **تضمین میشود** که در دنباله ورودی حداکثر یک حرف جا افتاده است. در صورتی که حرفی در دنباله جا نیفتاده بود، رشتهی خالی (`''`) را برگردانید.
+ **تضمین میشود** که اندازه آرایه ورودی حداقل ۲ است.
+ **تضمین میشود** که دنبالهی ورودی یا تنها شامل حروف کوچک است یا تنها شامل حروف بزرگ. بنابراین، حروف کوچک و بزرگ بهصورت همزمان در آرایه وجود نخواهند داشت.
# آنچه باید آپلود کنید
یک فایل *PHP* که تابع `missingLetter` در آن پیادهسازی شده است آپلود کنید.
PHP - حرف جا افتاده
علی در حال پیادهسازی سیستم ثبتنام برای یک مرکز آموزشی است و باید سیستمی را پیادهسازی کند تا متقاضیان ثبتنام عکسی را در سیستم آپلود کنند.
از آنجایی که عکسها برای این مرکز مهم است از علی خواسته شده تا قوانین سخت گیرانهای را روی عکسها اعمال کند.
علی برای پیادهسازی این سیستم از شما درخواست کمک کرده است.
# جزئیات پروژه
پروژهی اولیه را از [این لینک](/contest/assignments/24836/download_problem_initial_project/84147/) دانلود کنید.
<details class="grey">
<summary>ساختار فایلها</summary>
```
initial
├── app
│ ├── Console
│ │ └── Kernel.php
│ ├── Exceptions
│ │ └── Handler.php
│ ├── Http
│ │ ├── Controllers
│ │ │ ├── Controller.php
│ │ │ └── ImagesController.php
│ │ ├── Middleware
│ │ │ ├── Authenticate.php
│ │ │ ├── EncryptCookies.php
│ │ │ ├── PreventRequestsDuringMaintenance.php
│ │ │ ├── RedirectIfAuthenticated.php
│ │ │ ├── TrimStrings.php
│ │ │ ├── TrustHosts.php
│ │ │ ├── TrustProxies.php
│ │ │ └── VerifyCsrfToken.php
│ │ └── Kernel.php
│ ├── Models
│ │ └── User.php
│ └── Providers
│ ├── AppServiceProvider.php
│ ├── AuthServiceProvider.php
│ ├── BroadcastServiceProvider.php
│ ├── EventServiceProvider.php
│ └── RouteServiceProvider.php
├── bootstrap
│ ├── cache
│ │ ├── packages.php
│ │ └── services.php
│ └── app.php
├── config
│ ├── app.php
│ ├── auth.php
│ ├── broadcasting.php
│ ├── cache.php
│ ├── cors.php
│ ├── database.php
│ ├── filesystems.php
│ ├── hashing.php
│ ├── logging.php
│ ├── mail.php
│ ├── queue.php
│ ├── services.php
│ ├── session.php
│ └── view.php
├── database
│ ├── factories
│ │ └── UserFactory.php
│ ├── migrations
│ │ ├── 2014_10_12_000000_create_users_table.php
│ │ ├── 2014_10_12_100000_create_password_resets_table.php
│ │ └── 2019_08_19_000000_create_failed_jobs_table.php
│ └── seeders
│ └── DatabaseSeeder.php
├── public
│ ├── favicon.ico
│ ├── index.php
│ ├── robots.txt
│ └── web.config
├── resources
│ ├── css
│ │ └── app.css
│ ├── js
│ │ ├── app.js
│ │ └── bootstrap.js
│ ├── lang
│ │ └── en
│ │ ├── auth.php
│ │ ├── pagination.php
│ │ ├── passwords.php
│ │ └── validation.php
│ └── views
│ └── index.blade.php
├── routes
│ ├── api.php
│ ├── channels.php
│ ├── console.php
│ └── web.php
├── storage
│ ├── app
│ │ └── public
│ ├── framework
│ │ ├── cache
│ │ │ └── data
│ │ ├── sessions
│ │ ├── testing
│ │ └── views
│ └── logs
├── tests
│ ├── Feature
│ │ └── ExampleTest.php
│ ├── Unit
│ │ └── ExampleTest.php
│ ├── CreatesApplication.php
│ └── TestCase.php
├── README.md
├── artisan
├── composer.json
├── composer.lock
├── package.json
├── phpunit.xml
├── server.php
└── webpack.mix.js
```
</details>
<details class="brown">
<summary>راهاندازی پروژه</summary>
**برای اجرای پروژه، باید `php` و `composer` را از قبل نصب کرده باشید.**
+ ابتدا پروژهی اولیه را دانلود و از حالت فشرده خارج کنید.
+ دستور `composer install` را در پوشهی اصلی پروژه برای نصب نیازمندیها اجرا کنید.
</details>
بعد از اجرای پروژه شما در صفحه اصلی یک فرم را ملاحظه میکنید که وظیفه آپلود تصاویر را برعهده دارد و تمامی عکسها را به `ImagesController.php` و متد `save` میفرستد و شما باید محتوای این متد را طوری پیاده سازی کنید روی قوانین احراز هویت زیر روی عکس ها اعمال شود:
1. فایل عکس الزامی است.
2. فایل باید حتما عکس و به فرمتهای `jpeg,jpg,png` باشند.
3. شما باید قانون (rule) جدیدی را به هسته لاراول اضافه کنید تا فقط امکان آپلود عکس با نام های به فرمت **[عدد]File** مثل `File1.png` و `File342.png` و... را بدهد و اگر نام فایل به این فرمت نبود و زبان سایت انگلیسی بود، خطای `file name is incorrect` و اگر زبان سایت فارسی بود خطای `نام فایل صحیح نیست` را نمایش دهد.
```php
public function save(Request $request)
{
// TODO
}
```
# نکات
+ توجه داشته باشید که فایل عکس شما حتما باید در آدرس `storage/app/images` ذخیره شود.
+ شما تنها مجاز به ایجاد تغییرات در پوشههای `app` و `resources` هستید.
+ برای ولیدیت کردن عکس آپلود شده (به غیر از قانونی که اضافه میکنید) از پیام های پیش فرض لاراول استفاده کنید.
# آنچه باید آپلود کنید
پس از اعمال تغییرات، کل پروژه به غیر از پوشهی `vendor` را *Zip* کرده و آپلود کنید.
توجه کنید که نام فایل *Zip* اهمیتی ندارد.
Laravel - آپلود عکس
پدرام مدیر وبسایت آموزشی *کاپآموز* است. او در این روزهای کرونایی تصمیم گرفته است که یک نظرسنجی بین کاربران سایتش برگزار کند تا بداند کدام دورهها موردعلاقهی کاربران بودهاند. پدرام استراتژی خاصی را برای این نظرسنجی در نظر گرفته است. چنین نظرسنجیهایی معمولاً به اینصورت برگزار میشوند که هر کاربر دوره یا دورههای موردعلاقهی خود را از میان تمامی دورهها انتخاب میکند. از آنجایی که اکثر کاربران *کاپآموز* تمامی دورهها را گذراندهاند(!)، او از کاربران میخواهد یک رتبهبندی بین دورهها انجام دهند.
روند برگزاری نظرسنجی به اینصورت است که کاربر در هر مرحله با یک پرسش دوگزینهای مواجه میشود و باید از بین دو دوره، دورهای که علاقهی بیشتری به آن دارد را انتخاب کند. در انتها، رتبهبندی دورهها نمایش داده میشود.
# جزئیات پروژه
پروژهی اولیه را از [این لینک](/contest/assignments/24836/download_problem_initial_project/84143/) دانلود کنید. ساختار فایلهای این پروژه بهصورت زیر است:
```
interactive-sort
├── assets
├── test
├── index.php
└── items.txt
```
صفحهای که کاربر با آن تعامل دارد، `index.php` است. محتوای این صفحه بر حسب وضعیت فعلی باید تغییر کند.
فایل `items.txt` شامل نام دورهها است. در هر خط، نام یک دوره نوشته شده است. **تضمین میشود** که تا زمان نمایش نتایج، محتوای این فایل تغییر نمیکند.
## صفحهی پرسش
این صفحه باید بهصورت زیر باشد (به *ID* المانها و محتوای آنها توجه کنید):
```html
<body>
<p id="question">PHP course or Python course?</p>
<div id="choice1" class="button">PHP course</div>
<div id="choice2" class="button">Python course</div>
<form name="form" method="post">
<input type="hidden" id="choice" name="choice">
<input type="submit">
</form>
</body>
```
اگر کاربر گزینهی اول را انتخاب کند، فیلد `choice` با مقدار `1` با متد *POST* به `index.php` ارسال میشود. در غیر اینصورت، فیلد `choice` با مقدار `2` ارسال میشود.
گزینههایی که کاربر انتخاب میکند را به شکل دلخواه در *session* ذخیره کنید.
نتیجه بهصورت زیر خواهد بود:
![صفحهی پرسش](https://quera.ir/qbox/view/LIkt1y66p9/interactive-sort-1.png)
## صفحهی نتایج
این صفحه باید بهصورت زیر باشد (به *ID* المانها و محتوای آنها توجه کنید):
```html
<body>
<p id="result">Java course < Python course < PHP course</p>
</body>
```
نتیجه بهصورت زیر خواهد بود:
![صفحهی نتایج](https://quera.ir/qbox/view/lDtPP6aCS2/interactive-sort-2.png)
فرایند رتبهبندی را با استفاده از الگوریتمی نظیر *merge sort* انجام دهید تا با استفاده از کمترین مقایسهی ممکن بتوان رتبهبندی را انجام داد.
پس از نمایش نتیجهی رتبهبندی، با ارسال مجدد درخواست به `index.php`، کاربر همچنان باید با صفحهی نتایج روبهرو شود.
# مثال
در پروژهی اولیه، محتویات فایل `items.txt` بهصورت زیر است:
```
PHP course
Python course
Java course
```
مقادیر فوق، همان مقادیری هستند که کاربر باید مقایسه را بین آنها انجام دهد.
نمونهای از فرایند مقایسه را در زیر میبینید:
![مرتبسازی تعاملی](https://quera.ir/qbox/view/wD5ULdcuWd/interactive-sort.gif)
# نکات
+ فرایند مرتبسازی را با الگوریتمی نظیر *merge sort* انجام دهید. در صورت بالا بودن تعداد مقایسهها، امتیازی کسب نخواهید کرد.
+ انتخابهای کاربر را نمیتوانید در کوکی ذخیره کنید. برای ذخیرهسازی انتخابها، از *session* استفاده کنید (تنها کوکی `PHPSESSID` در نظر گرفته میشود).
# آنچه باید آپلود کنید
فایل `index.php` را آپلود کنید. اگر فایلهای دیگری نیز در کنار `index.php` به پروژه اضافه کردهاید، همهی فایلها را *Zip* کرده و ارسال کنید.
PHP - مرتبسازی تعاملی
نیما در این روزهای کرونایی حوصلهاش به شدت سر رفته. از این رو، تصمیم گرفته است تا با کمک دوست صمیمیاش، محمدرضا، یک وبسایت ساده بسازد که در آن بتوان *XO* بازی کرد. قرار است نیما *API* این بازی را طراحی کند و محمدرضا فرانت کار را پیش ببرد. اخیراً نیما درگیر امتحانات پایانترمش شده و میخواهد این وبسایت تا چند روز دیگر آماده شود. بنابراین، او از شما خواسته است تا *API* این بازی را پیادهسازی کنید.
# جزئیات پروژه
پروژهی اولیه را از [این لینک](/contest/assignments/24836/download_problem_initial_project/84145/) دانلود کنید.
<details class="grey">
<summary>ساختار فایلها</summary>
```
xo
├── app
│ ├── Console
│ │ └── Kernel.php
│ ├── Exceptions
│ │ └── Handler.php
│ ├── Http
│ │ ├── Controllers
│ │ │ ├── API
│ │ │ │ ├── AuthController.php
│ │ │ │ └── GameController.php
│ │ │ └── Controller.php
│ │ ├── Middleware
│ │ │ ├── Authenticate.php
│ │ │ ├── EncryptCookies.php
│ │ │ ├── PreventRequestsDuringMaintenance.php
│ │ │ ├── RedirectIfAuthenticated.php
│ │ │ ├── TrimStrings.php
│ │ │ ├── TrustHosts.php
│ │ │ ├── TrustProxies.php
│ │ │ └── VerifyCsrfToken.php
│ │ └── Kernel.php
│ ├── Models
│ │ ├── Game.php
│ │ ├── Move.php
│ │ └── User.php
│ └── Providers
│ ├── AppServiceProvider.php
│ ├── AuthServiceProvider.php
│ ├── BroadcastServiceProvider.php
│ ├── EventServiceProvider.php
│ └── RouteServiceProvider.php
├── bootstrap
│ ├── cache
│ │ ├── packages.php
│ │ ├── routes-v7.php
│ │ └── services.php
│ └── app.php
├── config
│ ├── app.php
│ ├── auth.php
│ ├── broadcasting.php
│ ├── cache.php
│ ├── cors.php
│ ├── database.php
│ ├── filesystems.php
│ ├── hashing.php
│ ├── logging.php
│ ├── mail.php
│ ├── queue.php
│ ├── services.php
│ ├── session.php
│ └── view.php
├── database
│ ├── factories
│ │ └── UserFactory.php
│ ├── migrations
│ │ ├── 2014_10_12_000000_create_users_table.php
│ │ ├── 2014_10_12_100000_create_password_resets_table.php
│ │ ├── 2019_08_19_000000_create_failed_jobs_table.php
│ │ ├── 2021_01_05_094004_create_games_table.php
│ │ └── 2021_01_05_095752_create_moves_table.php
│ ├── seeders
│ │ └── DatabaseSeeder.php
│ └── database.sqlite
├── public
│ ├── favicon.ico
│ ├── index.php
│ ├── robots.txt
│ └── web.config
├── resources
│ ├── css
│ │ └── app.css
│ ├── js
│ │ ├── app.js
│ │ └── bootstrap.js
│ ├── lang
│ │ └── en
│ │ ├── auth.php
│ │ ├── pagination.php
│ │ ├── passwords.php
│ │ └── validation.php
│ └── views
│ └── welcome.blade.php
├── routes
│ ├── api.php
│ ├── channels.php
│ ├── console.php
│ └── web.php
├── storage
│ ├── app
│ │ └── public
│ ├── framework
│ │ ├── cache
│ │ ├── sessions
│ │ ├── testing
│ │ └── views
│ ├── logs
│ │ └── laravel.log
│ ├── oauth-private.key
│ └── oauth-public.key
├── tests
│ ├── Feature
│ │ └── ExampleTest.php
│ ├── Unit
│ │ └── ExampleTest.php
│ ├── CreatesApplication.php
│ └── TestCase.php
├── README.md
├── artisan
├── composer.json
├── package.json
├── phpunit.xml
├── server.php
└── webpack.mix.js
```
</details>
<details class="brown">
<summary>راهاندازی پروژه</summary>
**برای اجرای پروژه، باید `php` و `composer` را از قبل نصب کرده باشید.**
+ ابتدا پروژهی اولیه را دانلود و از حالت فشرده خارج کنید.
+ دستور `composer install` را در پوشهی اصلی پروژه برای نصب نیازمندیها اجرا کنید.
+ دستور `php artisan migrate` را برای پیکربندی کامل پایگاه داده اجرا کنید.
+ دستور `php artisan passport:install` را برای پیکربندی *Laravel Passport* اجرا کنید.
</details>
برای احراز هویت در این پروژه از *Laravel Passport* استفاده شده است. همچنین، برای پایگاه داده از *SQLite* استفاده شده است.
## مدلها
این پروژه شامل ۳ مدل به شرح زیر است:
1. مدل `User`:
| نام فیلد | تعریف |
|------------|--------------|
| `id` | شناسهی کاربر |
| `username` | نام کاربری |
| `email` | آدرس ایمیل |
| `password` | رمز عبور |
2. مدل `Game`:
| نام فیلد | تعریف |
|----------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `id` | شناسهی بازی |
| `host_id` | شناسهی کاربر میزبان |
| `opponent_id` | شناسهی حریف |
| `is_host_turn` | یک `boolean` که بیانگر این است که الآن نوبت میزبان است یا خیر (مقدار پیشفرض آن `false` است)؛ مقدار آن در صورتی که بازی تمام شده باشد اهمیتی ندارد. |
| `status` | یک `enum` با مقدار پیشفرض `pending` به این معنا که بازی در انتظار تأیید است. اگر مقدار آن `rejected` باشد، یعنی حریف درخواست بازی را رد کرده است. اگر `ongoing` باشد، یعنی بازی در حال انجام است. اگر `win` باشد، یعنی میزبان برنده شده است. اگر `lose` باشد، یعنی حریف برنده شده است. اگر `tie` باشد، یعنی بازی مساوی شده است. |
3. مدل `Move`:
| نام فیلد | تعریف |
|--------------|------------------------------------------------------------------------------|
| `id` | شناسهی حرکت |
| `game_id` | شناسهی بازی |
| `position` | یک عدد در بازهی 1 تا 9 که بیانگر موقعیت حرکت است |
| `is_by_host` | یک `boolean` که بیانگر این است که این حرکت توسط میزبان صورت گرفته است یا خیر |
دو مورد زیر باید در مدلها پیادهسازی شوند:
1. متد `games` در مدل `User` را طوری پیادهسازی کنید که با اجرای متد `get` روی نتیجهی آن، بتوان آرایهای از بازیهایی که کاربر در آنها نقش میزبان یا حریف دارد را در اختیار داشت.
2. متد `getBoardAttribute` در مدل `Game` را طوری پیادهسازی کنید که صفحهی بازی را در قالب یک آرایهی ۳×۳ برگرداند. خانههای پرشده توسط شروعکنندهی بازی باید با `X` و خانههای پرشده توسط میزبان بازی باید با `O` نمایش داده شوند. خانههای خالی نیز باید با حرف `_` نمایش داده شوند. مثلاً اگر در یک بازی ابتدا حریف خانهی 9 را پر کند، سپس میزبان خانهی 5 را پر کند و در ادامه حریف خانهی 1 را پر کند، این متد باید چنین چیزی را برگرداند:
```php
[
['X', '_', '_'],
['_', 'O', '_'],
['_', '_', 'X']
]
```
## مسیرها
دو *route* زیر به کنترلر `API\AuthController` متصل هستند و باید پیادهسازی شوند:
1. **ثبتنام (`POST /register`):** سه فیلد `username`، `email` و `password` باید در بدنهی درخواست موجود باشند. همچنین، دو فیلد `username` و `email` باید در جدول `users` یکتا باشند. در صورتی که ورودی شرایط لازم را نداشتند، خطاهای پیشفرض *Validator* لاراول را در قالب *JSON* برگردانید. در غیر اینصورت، یک آرایه شامل کلید `token` با مقدار توکن تولیدشده توسط *Laravel Passport* را در پاسخ برگردانید.
2. **ورود (`POST /login`):** دو فیلد `username` و `password` باید در بدنهی درخواست موجود باشند. در صورتی که ورودی شرایط لازم را نداشتند، خطاهای پیشفرض *Validator* لاراول را در قالب *JSON* برگردانید. اگر نام کاربری یا رمز عبور نادرست بود، یک آرایه شامل کلید `error` با مقدار `invalid credentials` را در قالب *JSON* برگردانید. در غیر اینصورت، یک آرایه شامل کلید `token` با مقدار توکن تولیدشده توسط *Laravel Passport* را در پاسخ برگردانید.
پنج *route* زیر از *middleware* `auth:api` استفاده میکنند و نیازمند هدرهای `Accept: application/json` و `Authorization: Bearer token` هستند. این *route* ها به کنترلر `API\GameController` متصل هستند و باید پیادهسازی شوند:
3. **لیست بازیهای کاربر (`GET /games`):** بازیهایی که کاربر در آنها میزبان یا حریف دارد را در قالب *JSON* برگردانید.
4. **ساخت بازی جدید (`POST /games/create`):** فیلد `opponent` باید در بدنهی درخواست موجود باشد. در صورتی که ورودی شرایط لازم را نداشتند، خطاهای پیشفرض *Validator* لاراول را در قالب *JSON* برگردانید. در صورتی که کاربری با نام کاربری واردشده وجود نداشت، آرایهای شامل کلید `error` با مقدار `opponent does not exist` را با کد پاسخ *404* برگردانید. اگر نام کاربری واردشده با نام کاربری کاربر فعلی یکسان بود، آرایهای شامل کلید `error` با مقدار `you cannot play with yourself` را برگردانید. در غیر اینصورت، بازی را ایجاد کرده و آن را در پاسخ بهصورت *JSON* برگردانید.
5. **مشاهدهی اطلاعات بازی (`GET /games/{id}`):** در صورتی که بازیای با شناسهی واردشده وجود نداشت یا کاربر در آن میزبان یا حریف نبود، آرایهای شامل کلید `error` با مقدار `game does not exist` را با کد پاسخ *404* برگردانید. در غیر اینصورت، آبجکت بازی را در پاسخ برگردانید.
6. **تأیید درخواست بازی (`GET /games/accept/{id}`):** در صورتی که بازیای با شناسهی واردشده وجود نداشت یا کاربر در آن میزبان یا حریف نبود، آرایهای شامل کلید `error` با مقدار `game does not exist` را با کد پاسخ *404* برگردانید. اگر بازی در حال انجام بود، آرایهای شامل کلید `error` با مقدار `game is already ongoing` را برگردانید. اگر درخواست بازی قبلاً رد شده بود، آرایهای شامل کلید `error` با مقدار `game is already rejected` را برگردانید. اگر بازی خاتمه یافته بود، آرایهای شامل کلید `error` با مقدار `game is already finished` را برگردانید. در غیر اینصورت، وضعیت بازی را به `ongoing` تغییر داده و آرایهای شامل مقدار `success` را در قالب *JSON* برگردانید. اگر کاربر میزبان بازی بود، آرایهای شامل کلید `error` با مقدار `you cannot accept your games` را برگردانید.
7. **رد درخواست بازی (`GET /games/reject/{id}`):** در صورتی که بازیای با شناسهی واردشده وجود نداشت یا کاربر در آن میزبان یا حریف نبود، آرایهای شامل کلید `error` با مقدار `game does not exist` را با کد پاسخ *404* برگردانید. اگر بازی در حال انجام بود، آرایهای شامل کلید `error` با مقدار `game is already ongoing` را برگردانید. اگر درخواست بازی قبلاً رد شده بود، آرایهای شامل کلید `error` با مقدار `game is already rejected` را برگردانید. اگر بازی خاتمه یافته بود، آرایهای شامل کلید `error` با مقدار `game is already finished` را برگردانید. در غیر اینصورت، وضعیت بازی را به `rejected` تغییر داده و آرایهای شامل مقدار `success` را در قالب *JSON* برگردانید. اگر کاربر میزبان بازی بود، آرایهای شامل کلید `error` با مقدار `you cannot reject your games` را برگردانید.
8. **انجام حرکت در بازی (`POST /games/move/{id}`):** فیلد `position` باید با مقداری عددی و در بازهی 1 تا 9 در بدنهی درخواست موجود باشد. در صورتی که ورودی شرایط لازم را نداشتند، خطاهای پیشفرض *Validator* لاراول را در قالب *JSON* برگردانید. در صورتی که بازیای با شناسهی واردشده وجود نداشت یا کاربر در آن میزبان یا حریف نبود، آرایهای شامل کلید `error` با مقدار `game does not exist` را با کد پاسخ *404* برگردانید. اگر درخواست بازی در انتظار تأیید حریف بود، آرایهای شامل کلید `error` با مقدار `game is already pending` را برگردانید. اگر درخواست بازی قبلاً رد شده بود، آرایهای شامل کلید `error` با مقدار `game is already rejected` را برگردانید. اگر بازی خاتمه یافته بود، آرایهای شامل کلید `error` با مقدار `game is already finished` را برگردانید. اگر نوبت کاربر نبود، آرایهای شامل کلید `error` با مقدار `it is not your turn` را برگردانید (توجه کنید که همیشه حریف شروعکنندهی بازی است). اگر موقعیت حرکت در حال حاضر ثبت شده بود، آرایهای شامل کلید `error` با مقدار `cell is already full` را برگردانید. در غیر اینصورت، حرکت را ثبت کرده و آرایهای شامل مقدار `success` را در قالب *JSON* برگردانید. توجه کنید که پس از ثبت حرکت، باید بررسی کنید که آیا برندهی بازی (یا مساوی شدن بازی) میتواند تعیین شود یا خیر. در صورتی که این مورد قابل تشخیص بود، وضعیت بازی باید تغییر کند.
**توجه:** شما تنها مجاز به تغییر فایلهای موجود در پوشهی `/app` هستید.
# آنچه باید آپلود کنید
پس از اعمال تغییرات، کل پروژه به غیر از پوشهی `vendor` را *Zip* کرده و آپلود کنید. نام فایل *Zip* اهمیتی ندارد.
Laravel - ایکس او
**کد شما باید روی نسخهی استاندارد *MySQL* قابل اجرا باشد.** برای چک کردن سینتکس کد *SQL* خود میتوانید از **[این وبسایت](https://www.eversql.com/sql-syntax-check-validator/)** کمک بگیرید.
---
حمید یک برنامهنویس حرفهای است. او اخیراً به آشپزی علاقهمند شده و تصمیم گرفته تا یک وبسایت برای بهاشتراکگذاری دستور پختهای انحصاریاش راهاندازی کند. او میخواهد قابلیتهای پیشرفتهای را در وبسایتش ارائه دهد. برای مثال، این قابلیت که کاربران بتوانند مواد اولیهی موجودشان را در سایت ثبت کرده و سیستم بتواند لیست غذاهایی که با استفاده از مواد اولیهشان قابل پخت هستند را نمایش دهد. همچنین، کاربران امکان امتیازدهی (از ۱ تا ۵) به دستور پختها را دارند.
حمید بهخوبی از پس طراحی جداول دیتابیس سایتش برآمده، اما برای نوشتن کوئریهایش به کمک شما نیاز دارد.
# جزئیات پروژه
پایگاه دادهی اولیهی سایت حمید شامل ۶ جدول با اسامی و ساختارهای زیر است:
1. جدول کاربران (`users`):
| نام ستون | نوع | تعریف | ملاحضات |
|------------|----------------|------------------|------------------------------|
| `id` | `int(11)` | شناسهی کاربر | `primary key auto_increment` |
| `username` | `varchar(255)` | نام کاربری کاربر | |
2. جدول غذاها (`foods`):
| نام ستون | نوع | تعریف | ملاحضات |
|----------|----------------|-------------------|------------------------------|
| `id` | `int(11)` | شناسهی غذا | `primary key auto_increment` |
| `name` | `varchar(255)` | نام غذا | |
| `recipe` | `text` | متن دستور پخت غذا | |
3. جدول مواد اولیه (`ingredients`):
| نام ستون | نوع | تعریف | ملاحضات |
|------------------|-----------------|-----------------------|------------------------------|
| `id` | `int(11)` | شناسهی مادهی اولیه | `primary key auto_increment` |
| `name` | `varchar(255)` | نام مادهی اولیه | |
| `price_per_unit` | `decimal(10,2)` | قیمت واحد مادهی اولیه | |
4. جدول مواد اولیهی غذاها (`food_ingredients`):
| نام ستون | نوع | تعریف | ملاحضات |
|-----------------|-----------------|-------------------------|------------------------------|
| `id` | `int(11)` | شناسهی مادهی اولیهی غذا | `primary key auto_increment` |
| `food_id` | `int(11)` | شناسهی غذا | `foreign key (foods)` |
| `ingredient_id` | `int(11)` | شناسهی مادهی اولیه | `foreign key (ingredients)` |
| `amount` | `decimal(10,2)` | مقدار مادهی اولیه | |
5. جدول مواد اولیهی کاربران (`user_ingredients`):
| نام ستون | نوع | تعریف | ملاحضات |
|-----------------|-----------------|-------------------------|------------------------------|
| `id` | `int(11)` | شناسهی مادهی اولیهی کاربر | `primary key auto_increment` |
| `user_id` | `int(11)` | شناسهی کاربر | `foreign key (users)` |
| `ingredient_id` | `int(11)` | شناسهی مادهی اولیه | `foreign key (ingredients)` |
| `amount` | `decimal(10,2)` | مقدار مادهی اولیه | |
6. جدول امتیازات کاربران به غذاها (`ratings`):
| نام ستون | نوع | تعریف | ملاحضات |
|-----------|--------------|---------------|------------------------------|
| `id` | `int(11)` | شناسهی امتیاز | `primary key auto_increment` |
| `user_id` | `int(11)` | شناسهی کاربر | `foreign key (users)` |
| `food_id` | `int(11)` | شناسهی غذا | `foreign key (foods)` |
| `rate` | `tinyint(1)` | امتیاز | |
# مطلوبات
کوئریهای *SQL* خواستهشده از شما موارد زیر است (توجه کنید که هر کوئری نمرهای جداگانه دارد و اگر کوئری یک قسمت را نتوانستید بزنید، کوئریهایی که حل کردید را بفرستید و قسمت آن کوئری را خالی بگذارید):
1. حمید قبلاً دستور پختهایش را در کانال `@hamid_ashpazbashi2` به اشتراک میگذاشته. حال، نام کاربری کانالش را به `@hamid_ashpazbashi` تغییر داده است. او اکنون میخواهد همهی `@hamid_ashpazbashi2`های موجود در متن دستور پختها (ستون `recipe` جدول `foods`) را به `@hamid_ashpazbashi` تغییر دهد. این کوئری را برای او بنویسید.
2. شناسه، عنوان، میانگین امتیازات و تعداد آرای ۱۰ غذای برتر را برگردانید (ابتدا برحسب میانگین امتیازات بهصورت نزولی، سپس برحسب تعداد آرا بهصورت نزولی و سپس برحسب شناسهی غذا بهصورت نزولی). میانگین امتیازات را در قالب ستونی با نام `rating` و تعداد آرا را در قالب ستونی با نام `rate_count` برگردانید. اگر امتیازی به یکی از غذاهای موجود در نتیجه داده نشده بود، مقدار ستونهای `rating` و `rate_count` باید صفر باشد.
3. محتویات جدول غذاها را بههمراه ستون جدیدی با نام `total_price` برگردانید. مقدار این ستون باید برابر با جمع حاصلضرب قیمت واحد مواد اولیهی هر غذا در تعدادشان باشد. اگر مادهی اولیهای برای غذا ثبت نشده بود، مقدار این ستون باید صفر باشد.
4. شناسهی غذاهایی که کاربر با نام کاربری `quera` با استفاده از مواد اولیهش میتواند بپزد را در قالب ستونی با نام `id` برگردانید. نتایج باید بهترتیب نزولی شناسهی غذاها باشند. اگر مادهی اولیهای برای یک غذا ثبت نشده باشد، این غذا **نباید** در نتیجه وجود داشته باشد.
# آنچه باید آپلود کنید
کد خود را در قالب زیر، در یک فایل با پسوند `sql` قرار داده و آن را ارسال کنید.
```sql
-- Section1
your 1st query here
-- Section2
your 2nd query here
-- Section3
your 3rd query here
-- Section4
your 4th query here
```