مهدی برنامهنویس خفنی است و پروژههای خفنی انجام میدهد. دوستان او از نحوهی پیادهسازی سیستم داوری کوئرا در عجباند، اما مهدی به آنها میگوید *پیادهسازی جاجی مثل کوئرا عین آب خوردنه*! مهدی میخواهد این موضوع را به دوستانش اثبات کند، اما در حال حاضر مشغول انجام پروژههای خفن است و فرصت انجام این کار را ندارد.
از شما میخواهیم این موضوع را به دوستان مهدی اثبات کنید.
# جزئیات پروژه
پروژهی اولیه را از [این لینک](/contest/assignments/35048/download_problem_initial_project/124280/) دانلود کنید.
<details class="grey">
<summary>ساختار فایلها</summary>
```
judge-api
├── app
│ ├── Console
│ ├── Exceptions
│ ├── Http
│ ├── Jobs
│ │ └── JudgeSubmission.php
│ ├── Judge
│ │ ├── InputOutputJudge.php
│ │ ├── Judge.php
│ │ └── JudgeResult.php
│ ├── Models
│ │ ├── Submission.php
│ │ └── User.php
│ └── Providers
├── bootstrap
├── config
├── database
├── public
├── resources
├── routes
├── storage
├── tests
├── 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` را در پوشهی اصلی پروژه برای نصب نیازمندیها اجرا کنید.
+ برای اجرای تستهای نمونه، میتوانید از دستور `php artisan test` استفاده کنید.
</details>
همانطور که میدانید، سیستم داوری کوئرا (در حالت ورودی/خروجی) به اینصورت است که یک رشته بهعنوان *stdin* به یک برنامه داده میشود و در انتها، نتیجهی اجرای برنامه دریافت میشود.
## مدلها
علاوه بر مدل پیشفرض `User`، مدلی با نام `Submission` در برنامه تعریف شده است. مایگریشنها و روابط بین مدلها از قبل برقرار شدهاند. با مطالعهی این موارد، باید با ساختار مدلهای برنامه آشنا شوید.
## کلاس `App\Judge\JudgeResult`
از این کلاس برای نگهداری اطلاعات مربوط به داوری ارسالها استفاده میشود.
```php app/Judge/JudgeResult.php laravel
class JudgeResult
{
const SUCCESS = 0;
const TIME_LIMIT_EXCEEDED = 1;
const RUNTIME_ERROR = 2;
const SYNTAX_ERROR = 3;
public function __construct(
public string $stderr,
public string $stdout,
public int $status
) {}
}
```
## اینترفیس `App\Judge\Judge`
این اینترفیس شامل یک متد با نام `run` است که پارامترهای آن بهصورت زیر هستند:
+ `code`: متن کد
+ `timeLimit`: محدودیت زمان برحسب **میلیثانیه**
+ `stdin`: ورودی برنامه
```php app/Judge/Judge.php laravel
interface Judge
{
public function run(string $code, int $timeLimit, string $stdin = ''): JudgeResult;
}
```
## کلاس `App\Judge\InputOutputJudge`
این کلاس یک پیادهسازی از اینترفیس `App\Judge\Judge` است که باید کدهای *PHP* را اجرا کند و نتیجه را در قالب آبجکتی از کلاس `App\Judge\JudgeResult` برگرداند. مقدار پراپرتیهای آبجکت خروجی باید مطابق توضیحات زیر باشد:
+ اگر کد سینتکس ارور داشته باشد، مقدار `status` باید برابر با `JudgeResult::SYNTAX_ERROR` باشد و مقدار `stderr` و `stdout` باید برابر با رشتهی خالی باشد.
+ اگر اجرای برنامه در زمان مشخصشده خاتمه یابد و دادهای توسط برنامه در `stderr` نوشته نشده باشد، مقدار `status` باید برابر با `JudgeResult::SUCCESS` باشد، مقدار `stderr` باید برابر با رشتهی خالی باشد و مقدار `stdout` باید برابر با خروجی برنامه باشد.
+ اگر اجرای برنامه در زمان مشخصشده خاتمه یابد و دادهای توسط برنامه در `stderr` نوشته شده باشد، مقدار `status` باید برابر با `JudgeResult::RUNTIME_ERROR` باشد، مقدار `stderr` باید برابر با محتویات `stderr` باشد و مقدار `stdout` باید برابر با رشتهی خالی باشد.
+ اگر اجرای برنامه در زمان مشخصشده خاتمه نیابد، فارغ از این که دادهای توسط در `stdout` یا `stderr` نوشته شده باشد، مقدار `status` باید برابر با `JudgeResult::TIME_LIMIT_EXCEEDED` باشد و مقدار `stderr` و `stdout` باید برابر با رشتهی خالی باشد.
## جاب `JudgeSubmission`
این جاب شناسهی یک `Submission` را دریافت میکند. وظیفهی این جاب، داوری یک `Submission` است. متد `handle` این جاب را طوری پیادهسازی کنید که ابتدا مقدار ستون `status` مربوط به `Submission` را به `judging` تغییر دهد، سپس داوری را با استفاده از کلاس `InputOutputJudge` انجام دهد و در نهایت، `status`، `stderr` و `stdout` را مقداردهی کند و تغییرات را در دیتابیس ذخیره کند.
## احراز هویت
پکیج `laravel/sanctum` در این پروژه نصب شده و از آن میتوانید برای احراز هویت استفاده کنید. توکنهای احراز هویت هنگام داوری توسط این پکیج تولید میشوند. هنگام ارسال درخواستها، مقدار `header` برابر با یک توکن `Bearer` قرار داده میشود و مقدار هدر `Accept` برابر با `application/json` خواهد بود.
%align_right_start%
## *endpoint* های *API*
%align_end%
در این برنامه باید سه *endpoiont* بهصورت زیر تعریف کنید. همهی این *endpoint* باید نیازمند احراز هویت کاربر باشند. در غیر اینصورت، کد پاسخ `401` باید برگردانده شود:
+ `GET /api/submissions`: با ارسال این درخواست، کاربر باید لیست ارسالهایش را در قالب یک آرایه ببیند (باید کالکشنی از `Submission`ها را به *JSON* تبدیل کرده و آن را برگردانید). کد پاسخ باید برابر با `200` باشد.
+ `POST /api/submissions`: با ارسال این درخواست، باید یک `Submission` به `Submission`های کاربر اضافه شود. **تضمین میشود** که مقادیر `code`، `time_limit` و `stdin` در بدنهی درخواست موجود خواهند بود. همچنین، جاب `JudgeSubmission` مربوط به `Submission` ارسالشده باید به صفی با عنوان `judge` اضافه شود. کد پاسخ باید برابر با `201` باشد.
+ `GET /api/submissions/{submission_id}`: با ارسال این درخواست، کاربر باید اطلاعات `Submission` با شناسهی `submission_id` را مشاهده کند (باید آبجکت `Submission` را به *JSON* تبدیل کرده و آن را برگردانید). اگر `Submission` وجود نداشته باشد یا متعلق به کاربر نباشد، کد پاسخ باید برابر با `404` باشد. در غیر اینصورت، کد پاسخ باید برابر با `200` باشد.
# نکات
+ داوری در یک سیستم لینوکسی صورت میگیرد. بنابراین میتوانید از امکانات خط فرمان آن استفاده کنید.
+ شما تنها مجاز به اعمال تغییرات در پوشههای `app` و `routes` هستید (میتوانید فایلهای جدیدی نیز در این پوشهها ایجاد کنید).
# آنچه باید آپلود کنید
پس از پیادهسازی موارد خواستهشده، پوشههای `app` و `routes` را زیپ کرده و آپلود کنید.