برای *سَلیب* و *اِبلیس* سوال شده بود که چه کسی در کدنویسی مهارت بیشتری دارد. بنابراین آنها تصمیم گرفتند تا پروژه ای شبیه به بخش [مسابقات کوئرا](https://quera.ir/contest/) پیادهسازی کنند. سپس در آن به مسابقه بپردازند تا مشخص شود که کدامیک، کُدزن قَهارتری است!
اما در پیادهسازی بخشهایی از پروژه به مشکل خوردهاند و از شما میخواهند تا این بخشها را تکمیل کنید تا هر چه سریعتر بتوانند به مسابقهی خود بپردازند.
## پروژه اولیه
پروژه اولیه را از [این لینک](/problemset/assignments/4367/download_problem_initial_project/102251/) دانلود کنید.
ساختار فایلهای این پروژه به صورت زیر است.
```
quera_contest
├── accounts
│ ├── migrations
│ │ ├── 0001_initial.py
│ │ └── __init__.py
│ ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── models.py
│ ├── permissions.py
│ ├── serializers.py
│ ├── tests.py
│ ├── urls.py
│ ├── validators.py
│ └── views.py
├── contests
│ ├── migrations
│ │ ├── 0001_initial.py
│ │ └── __init__.py
│ ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── models.py
│ ├── <mark class="yellow" title="این فایل را تغییر دهید"> > query.py < </mark>
│ ├── tests.py
│ └── views.py
├── fixtures
│ ├── sample_contest.json
│ └── sample_data.json
├── problems
│ ├── migrations
│ │ ├── 0001_initial.py
│ │ └── __init__.py
│ ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── <mark class="yellow" title="این فایل را تغییر دهید"> > models.py < </mark>
│ ├── tests.py
│ └── views.py
├── tests
│ ├── __init__.py
│ └── testsample.py
├── manage.py
└── requirements.txt
```
## جزئیات
### مدلهایی که شما باید پیادهسازی کنید
<details class="blue">
<summary>
**مدل** `Problem`
</summary>
هر شئ این مدل معادل یک مسئله (*problem*) در کوئراست.
این مدل دارای ویژٰگیهای زیر است:
+ فیلد `name`:
نشاندهنده نام مسئله میباشد و از نوع `CharField` است. باید حداکثر طولی برابر با 50 کاراکتر داشته باشد.
+ فیلد `description`:
نشاندهنده توضیحات مسئله میباشد و از نوع `CharField` است. باید حداکثر طولی برابر با 1000 کاراکتر داشته باشد.
+ فیلد `writer`:
نشان دهنده طراح و نویسنده مسئله میباشد و از طریق رابطهی `many-to-one` به مدل `User` وصل میشود.
**توجه داشته باشید** مدل `User` درون اپ `accounts` در پروژه اولیه پیادهسازی شده و شما نیازی به ایجاد هیچ تغییری در آن ندارید.
+ فیلد `score`:
نشاندهنده نمره مسئله میباشد و از نوع `PositiveIntegerField` است. باید مقدار پیشفرضی برابر با 100 داشته باشد.
</details>
<details class="blue">
<summary>
**مدل** `Submission`
</summary>
هر شئ این مدل معادل یک پاسخ ارسال شده برای سیستم داوری کوئراست.
این مدل دارای ویژگیهای زیر است:
+ فیلد `submitted_time`:
نشاندهنده زمان پاسخ ارسالی میباشد و از نوع `DateTimeField` است.
+ فیلد `participant`:
نشان دهنده فرستنده پاسخ ارسالی میباشد و از طریق رابطهی `many-to-one` به مدل `User` وصل میشود و دارای آرگومان `related_name="submissions"` است.
**توجه داشته باشید** مدل `User` درون اپ `accounts` در پروژه اولیه پیادهسازی شده و شما نیازی به ایجاد هیچ تغییری در آن ندارید.
+ فیلد `problem`:
نشان دهنده مسئله پاسخ ارسالی میباشد و از طریق رابطهی `many-to-one` به مدل `Problem` وصل میشود و دارای آرگومان `related_name="submissions"` است.
+ فیلد `code`:
نشاندهنده آدرس ذخیره پاسخ ارسالی میباشد و از نوع `URLField` است. باید حداکثر طولی برابر با 200 کاراکتر داشته باشد.
+ فیلد `score`:
نشاندهنده نمره مسئله میباشد و از نوع `PositiveIntegerField` است. باید مقدار پیشفرضی برابر با 0 داشته باشد.
</details>
## کوئریهایی که شما باید پیادهسازی کنید
**اکیداً توصیه میشود** پیش از حل این بخش مدل `Contest` موجود در اپ `contests` را مطالعه کنید و با این مدل به خوبی آشنا شوید.
<details class="blue">
<summary>
**کوئری** `list_problems`
</summary>
این کوئری `id` یک `Contest` را ورودی گرفته و تمامی مسائل آن `Contest` را در قالب یک کوئریست بازمیگرداند.
مثالِ خروجی این تابع به صورت زیر است:
```python
<QuerySet [<Problem: Problem object (1)>, <Problem: Problem object (2)>, <Problem: Problem object (3)>]>
```
</details>
<details class="blue">
<summary>
**کوئری** `list_users`
</summary>
این کوئری `id` یک `Contest` را ورودی گرفته و تمامی کاربرانی که در آن `Contest` شرکت داشتهاند را در قالب یک کوئریست بازمیگرداند.
مثال خروجی این تابع به صورت زیر است:
```python
<QuerySet [<User: SAliB>, <User: Saeid>, <User: Ali>]>
```
</details>
<details class="blue">
<summary>
**کوئری** `list_submissions`
</summary>
این کوئری `id` یک `Contest` را ورودی گرفته و تمامی ارسالهای آن `Contest` را به ترتیب زمان ارسال (`submitted_time` در مدل `Submission`) از آخرین به اولین ارسال در قالب یک کوئریست بازمیگرداند.
مثال خروجی این تابع به صورت زیر است:
```python
<QuerySet [<Submission: Submission object (12)>, <Submission: Submission object (6)>, <Submission: Submission object (16)>, <Submission: Submission object (5)>, <Submission: Submission object (11)>, <Submission: Submission object (15)>, <Submission: Submission object (14)>, <Submission: Submission object (4)>, <Submission: Submission object (10)>, <Submission: Submission object (9)>, <Submission: Submission object (3)>, <Submission: Submission object (8)>, <Submission: Submission object (2)>, <Submission: Submission object (13)>, <Submission: Submission object (1)>, <Submission: Submission object (7)>]>
```
</details>
<details class="blue">
<summary>
**کوئری** `list_problem_submissions`
</summary>
این کوئری `id` یک `Contest` و `id` یک مسئله را ورودی گرفته و تمامی ارسالهای آن مسئله در `Contest` را به ترتیب زمان ارسال (`submitted_time` در مدل `Submission`) از آخرین به اولین ارسال در قالب یک کوئریست بازمیگرداند.
مثال خروجی این تابع به صورت زیر است:
```python
<QuerySet [<Submission: Submission object (9)>, <Submission: Submission object (8)>, <Submission: Submission object (2)>, <Submission: Submission object (13)>, <Submission: Submission object (1)>, <Submission: Submission object (7)>]>
```
</details>
<details class="blue">
<summary>
**کوئری** `list_user_submissions`
</summary>
این کوئری `id` یک `Contest` و `id` یک کاربر را ورودی گرفته و تمامی ارسالهای آن کاربر در `Contest` را به ترتیب زمان ارسال (`submitted_time` در مدل `Submission`) از آخرین ارسال به اولین ارسال در قالب یک کوئریست بازمیگرداند.
مثال خروجی این تابع به صورت زیر است:
```python
<QuerySet [<Submission: Submission object (6)>, <Submission: Submission object (5)>, <Submission: Submission object (4)>, <Submission: Submission object (3)>, <Submission: Submission object (2)>, <Submission: Submission object (1)>]>
```
</details>
<details class="blue">
<summary>
**کوئری** `list_problem_user_submissions`
</summary>
این کوئری `id` یک `Contest`، `id` یک کاربر و `id` یک مسئله را ورودی گرفته و تمامی ارسالهای آن کاربر در `Contest` برای آن مسئله را به ترتیب زمان ارسال (`submitted_time` در مدل `Submission`) از آخرین به اولین ارسال در قالب یک کوئریست بازمیگرداند.
مثال خروجی این تابع به صورت زیر است:
```python
<QuerySet [<Submission: Submission object (2)>, <Submission: Submission object (1)>]>
```
</details>
<details class="blue">
<summary>
**کوئری** `list_users_solved_problem`
</summary>
این کوئری `id` یک `Contest` و `id` یک مسئله را ورودی گرفته و تمامی کاربرانی که آن مسئله را در `Contest` حل کردهاند به ترتیب زمان ارسال (`submitted_time` در مدل `Submission`) از آخرین به اولین ارسال در قالب یک کوئریست بازمیگرداند.
**توجه کنید** تنها در صورتی یک پاسخ ارسالی درست است که نمره آن برابر با نمره اصلی مسئله باشد.
مثال خروجی این تابع به صورت زیر است:
```python
<QuerySet [<User: SAliB>]>
```
</details>
<details class="blue">
<summary>
**کوئری** `user_score`
</summary>
خروجی این کوئری از جنس عدد است. این کوئری `id` یک `Contest` و `id` یک کاربر را ورودی گرفته و مجموع امتیاز آن کاربر در `Contest` را خروجی میدهد.
**توجه داشته باشید** امتیاز هر کاربر در یک `Contest` برابر با جمع بیشترین امتیازات آن کاربر برای هر سوال است. مثلاً اگر یک کاربر برای سوال اول، امتیازات ۱۰۰، ۱۵۰ و ۲۰۰ را کسب کرده و برای سوال دوم، امتیازات ۵۰ و ۱۰۰ را کسب کرده باشد؛ امتیاز او برابر با بیشترین امتیاز کسب شده در سوال اول (۲۰۰) بعلاوه بیشترین امتیاز کسب شده در سوال دوم (۱۰۰) است (یعنی ۳۰۰).
مثال خروجی این تابع به صورت زیر است:
```python
600
```
</details>
<details class="blue">
<summary>
**کوئری** `list_final_submissions`
</summary>
این کوئری `id` یک `Contest` را ورودی گرفته و ارسالهای نهایی آن `Contest` را به ترتیب آیدی شرکتکننده (`participant_id` در مدل `Submission`) از آخرین به اولین ارسال، در قالب یک کوئریست بازمیگرداند.
مثال خروجی این تابع به صورت زیر است:
```python
<QuerySet [{'participant_id': 1, 'problem_id': 1, 'score__max': 100}, {'participant_id': 1, 'problem_id': 2, 'score__max': 200}, {'participant_id': 1, 'problem_id': 3, 'score__max': 300}, {'participant_id': 2, 'problem_id': 1, 'score__max': 100}, {'participant_id': 2, 'problem_id': 2, 'score__max': 120}, {'participant_id': 3, 'problem_id': 1, 'score__max': 100}, {'participant_id': 3, 'problem_id': 2, 'score__max': 200}, {'participant_id': 3, 'problem_id': 3, 'score__max': 240}]>
```
</details>
## زیرمسئلهها
| امتیاز | بخش |
|:------------------:|:------------------:|
| ۱۰ | Problem Model |
| ۱۰ | Submission Model |
| ۱۵ | Query List Problem |
| ۱۵ | Query List Users |
| ۱۵ | Query List Submissions |
| ۲۰ | Query List Problem Submissions |
| ۲۰ | Query List User Submissions |
| ۲۵ | Query List Problem User Submissions |
| ۳۰ | Query List User Solved Problem |
| ۴۰ | Query User Score |
| ۴۰ | Query List Final Submissions |
## امکانات اضافه
در صورتی که علاقمندید که خودتان به صورت دستی کوئریهای خود را امتحان کنید و از درستی آنها اطمینان حاصل کنید، یا اینکه به بررسی بیشتر از این تمرین بپردازید، برای راحتی بیشتر شما، فایلهای مایگریشنها ساخته شدهاند و شما کافیست پس از پیادهسازی فایل `problems/models.py` جهت ایجاد پایگاهداده، یک بار دستور `migrate` را اجرا کنید.
علاوهبر این، یک سری دادهی از پیش آماده شده، فراهم شده که بعد از اجرای دستور `migrate`، میتوانید آنها را وارد پایگاهدادهی پروژهی خود کنید. به این منظور، دستور زیر را اجرا کنید. میتوانید از این دادهها به جهت تست کردن کوئریهای خود استفاده کنید.
**۱. ایجاد پایگاهداده**
```bash
python manage.py migrate
```
**۲. وارد کردن دادههای از پیش آماده شده (fixture)**
```bash
python manage.py loaddata fixtures/sample_data.json
python manage.py loaddata fixtures/sample_contest.json
```
در صورتی که علاقمند به تست نیستید، نیازی به ایجاد پایگاهداده و وارد کردن دادههای آزمایشی نیست، و تنها کافیست که در فایل `query.py` کوئریهای خود را بنویسید و از کوئرا جهت امتحان کردن درستی کوئریهایتان استفاده کنید.
## تست نمونه
در فایلهای اولیهای که دانلود کردید یکسری داده اولیه به عنوان نمونه قرار داده شده است. میتوانید قبل از فرستادن سوال در سایت، این تستها را ببینید تا با نحوه داوری ما آشنا شوید و از پاسخ خود اطمینان حاصل نمایید.
تستها را میتوانید با دستور زیر اجرا کنید:
```shell terminal terminal
python manage.py test
```
## نکات
+ شما تنها مجوز ایجاد تغییرات در فایلهای زیر را دارید و **تمامی تغییرات دیگر شما** در فایلهای پروژه **نادیده گرفته خواهند شد.**
+ فایل `contests/query.py`
+ فایل `problems/models.py`
+ فراموش نکنید که میتوانید با مطالعهی `testsample.py` با روش تست کردن مدلها آشنا شوید.
## نحوه ارسال
یک فایل _ZIP_ حاوی همهی فایلهای پروژه، آپلود کنید. نام فایل _ZIP_ اهمیتی ندارد.