در این سوال قصد داریم مساحت چهار شکل دایره، مستطیل، مربع و مثلث رو حساب کنیم.
از شما میخواهیم که یک تابع به نام `get_func(ls)` بنویسید که یک لیست از رشتهها (که نام اشکال مختلف دو بعدی هستند) را ورودی میگیرد و برای هر رشته تابع محاسبهگر مساحت آن را به دست آورده و به همان ترتیب لیست ورودی در لیستی جدید ذخیره کرده و خروجی میدهد.
# توابع محاسبهگر مساحت
+ مربع: تابع محاسبهگر مساحت مربع فقط یک آرگومان دارد و آن طول ضلع مربع است. خروجی آن مساحت مربع بر اساس طوب داده شده است.
+ دایره: تابع محاسبهگر مساحت دایره شعاع دایره را به عنوان آرگومان گرفته و مساحت دایره را خروجی میدهد.
+ مستطیل: تابع محاسبهگر مساحت مستطیل دو آرگومان طول و عرض را گرفته و مساحت مستطیل را خروجی میدهد.
+ مثلث: تابع محاسبهگر مثلث دو آرگومان ارتفاع و قاعده را گرفته و مساحت مثلث را خروجی میدهد.
برای مثال:
```python
ls = get_func(['square', 'circle', 'rectangle', 'triangle'])
print(ls[0](1))
print(ls[1](2))
print(ls[2](2, 4))
print(ls[3](4, 5))
```
خروجی کد بالا:
```
1
12.566370614359172
8
10.0
```
تابع `get_func` را در فایل `solution.py` پیاده سازی کنید و فایل کد خود را زیپ و ارسال کنید.
مساحت
فرض کنید که در یک فایل پایتون چند کلاس وجود دارد و به مجموعه کل آن کلاسها $S$ میگوییم. گراف جهت دار $G$ را از روی مجموعه $S$ به این شکل میسازیم که راس $v$ به راس $u$ یال دارد اگر و فقط اگر کلاس $v$ از کلاس $u$ به صورت مستقیم ارث برده باشد. برای مثال به کد زیر دقت کنید:
```python
class A:
def f(self, a, b):
return a + b
class B(A):
def g(self, a):
return a*10
class C(A):
def g(self, a):
return a**2
class D(C, B):
pass
```
گراف کلاسهای بالا:
![مثل](https://quera.ir/qbox/view/CQz28hUZyI/graph__3_.png)
در این مثال $B$ و $C$ از $A$ ارث بردهاست و کلاس $D$ هم از کلاس $C$ و $B$ ارث برده است.
حال کد زیر را در نظر بگیرید
```python
d = D()
print(d.f(10, 20)) # 30
```
کلاس `C` و `B` تابع `f` را از کلاس `A` به ارث بردهاند و کلاس `D` این تابع را از این دو کلاس به ارث بردهاست. پس دو مسیر `D-B-A` و `D-C-A` برای صدا شدن تابع `f` قابل تصور است که در این سوال (مانند قانون خود مفسر پایتون) در ارثبری کلاسی که زودتر (چپتر در پرانتز جلوی تعریف کلاس) نوشته شده را مقدم در نظر میگیریم. یعنی مسیر `D-C-A` را برای `d.f` در نظر میگیریم.
در کد زیر برای مثال:
```python
d = D()
print(d.g(20)) # 400
```
در اینجا تابع `g` هم در کلاس `B` و هم در کلاس `C` وجود دارد ولی طبق مفسر پایتون، مسیر مورد نظر در این سوال مسیر `D-C` برای `d.g` است.
حال لیست کلاسها در اختیار شما قرار میگیرد و شما باید با ایجاد تغییراتی در کلاسها شرایطی را ایجاد کنید که با صدا کردن هر تابع. مسیر صدا شدن آن تابع در شی کلاس `Record` که به شما ورودی داده میشود ذخیره شود.
این کار در قالب یک تابع به نام `rearrange(ls, rec)` باید صورت بگیرد که `ls` لیست کلاسهاست و `rec` آن شی مورد نظر از کلاس `Record` هست که باید مسیرها در آن ذخیره شود.
+ تضمین میشود قبل از صدا کردن هر تابع مسیر `rec` خالی شود.
+ تضمین میشود هیچ کلاسی از دو کلاسی که از هم ارث بردهاند به صورت مستقیم ارث نبرد.
+ تضمین میشود هیچ کلاسی از کلاسی بیرون از لیست داده شده جز `object` ارث نبرد.
+ دقت کنید که ممکن است توابع تعریف شده همدیگر را صدا کنند. (و این جزو مسیر به شمار نمیآید)
برای درک بهتر به کد زیر و خروجی آن دقت کنید.
```python
from record import Record
from solution import rearrange # your implemented function
class A:
def f(self, a, b):
return a + b
class B(A):
def g(self, a):
return a*10
class C(A):
def g(self, a):
return a**2
class D(C, B):
pass
rec = Record()
rearrange([A, B, C, D], rec)
d = D()
print(d.f(10, 20))
print(rec.get_path_list())
```
خروجی کد بالا:
```
30
[<class '__main__.D'>, <class '__main__.C'>, <class '__main__.A'>]
```
# کلاس `Record`:
کد این کلاس در [این](https://quera.ir/qbox/download/ftsfGwM6Y2/record.py) لینک قرار دارد. (لازم نیست این فایل را همراه راهحل ارسال کنید)
این کلاس در کنار فایل ارسالی شما قرار میگیرد و شما میتوانید آن را `import` کنید. این کلاس دارای سه تابع زیر است.
+ تابع `add_node(node)`: این تابع یک عضو گرفته (که در این سوال باید یک کلاس باشد) و آن را به لیست مسیر اضافه میکند.
+ تابع `get_path_list()`: این تابع لیست مسیر را خروجی میدهد.
+ تابع `refresh()`: این تابع مسیر ذخیره شده را خالی میکند.
تابع `rearrange(ls, record)` را در فایل `solution.py` پیاده سازی کنید و فایل `solution.py` را زیپ کرده و ارسال کنید.
# نمرهدهی:
این سوال دارای ۴ تست است که ۲ تست آن یک مسیر ساده، یک تست گرافی مانند گراف مثال زده شده و تست دیگر یک گراف پیچیده میباشد. اگر برای مثال فقط برای مسیرها حل کردید جواب خود را ارسال کنید، بخشی از نمره به شما تعلق میگیرد.
مسیر وراثت
احتمالا شما هم تا به حال از یک فروشگاه آنلاین خرید کردهاید. در هر فروشگاه آنلاین یک سبد خرید یا `cart` وجود دارد که محصولات انتخاب شده در آن نمایش داده میشوند و برای هر محصول میتوان بعضی خصوصیات آن محصول مانند تعداد، رنگ و ... را تغییر داد.
حال ما میخواهیم یک فروشگاه آنلاین بنویسیم و قسمتی از پروژه را نیز نوشتهایم و از شما میخواهیم در نوشتن فرمِ سبد خرید به ما کمک کنید. پروژهی فعلی را میتوانید از این [لینک](https://quera.ir/qbox/download/otKHcrVkFn/shop.zip) دانلود کنید.
همانطور که میبینید، در پروژه یک `app` به نام `shop` و در آن دو مدل `Color` و `Product` وجود دارد.
در فایل `forms.py` یک فرم با نام `CartForm` وجود دارد که شما باید این کلاس را به شکل زیر تکمیل کنید.
**توجه**: در ورودی `kwargs` تابع `__init__` یک کلید به نام `items` وجود دارد که لیست `product` ها را نشان میدهد.
#### **اضافه کردن فیلدها**
شما باید به ازای هر `product` ای که به فرم شما پاس داده میشود، دو فیلد تعداد و رنگ را به شکل زیر قرار دهید:
+ **تعداد:** این فیلد باید از نوع `IntegerField` باشد و نام آن `number_<product.id>` باشد که در آن *<product.id>* آیدی آن محصول است. برای این فیلد، باید مقدار پیشفرض ۱ را در نظر بگیرید. و `label` آن هم باید نام محصول باشد.
+ **رنگ:** این فیلد از نوع `ChoiceField` میباشد و نام آن `color_<product.id>` است که در آن *<product.id>* آیدی آن محصول است. این فیلد لیستی از رنگهای موجود برای محصول خاص را نشان میدهد. مقدار `label` این فیلد هم باید `'color'` باشد. تضمین میشود که هیچ محصولی بدون رنگ نیست.
موارد خواسته شده باید در تابع `__init__` به `self.fields` اضافه شوند. همچنین به ازای هر دو مورد بالا مقدار `required` باید `False` باشد.
توجه کنید که هر دو این فیلدها در نهایت حتما باید مقدار داشته باشند بدین معنی که اگر در `request.POST` داده برای یک فیلد فرستاده نشد، باید خودتان برایش مقداری قرار دهید. برای فیلدهای "تعداد" مقدار ۱ و برای فیلدهای "رنگ"، کوچکترین رنگ موجود در لیست رنگهای آن کالا (از نظر الفبایی) باید قرار بگیرد.
#### برای مثال:
```
>>> product.id
5
>>> product.colors_available
{'red', 'blue', 'white'}
```
حال یک درخواست POST با داده های خالی `{}` ارسال میشود. در این صورت باید بعد از ایجاد فرم و صدا شدن تابع ()is_valid، متغییر cleaned_data به شکل زیر باشد:
```
{'number_5' = 1, 'color_5' = 'blue'}
```
زیرا رنگ `blue` از نظر الفبایی از دو رنگ دیگر کوچکتر است.
در فایل `views.py` یک تابع به نام `make_json` قرار دارد که cleand_data فرم مورد نظر را به شکل json با فرمت خاص برمیگرداند. نیازی نیست شما در این تابع تغییری ایجاد کنید یا از آن استفاده کنید.
**فایل آپلودی**
یک فایل zip. که درون آن یک پوشه `shop` وجود دارد که شامل یک فایل `forms.py` است. توجه کنید در صورتی که فایلهای اضافی ارسال کنید، حذف خواهند شد.
```
<Your-zip-name>.zip
└── shop
└── forms.py
```
فروشگاه آنلاین
امروزه سایتهای سفارش آنلاین غذا بسار زیاد و همهگیر شدهاند، و مخصوصا شادی زیادی را برای ما برنامه نویسها فراهم کردهاند. حالا یکی از این سایتها تصمیم گرفته است برای بهتر کردن خدماتش و کمک به مشتریهای سایت در انتخاب غذا، بخش کامنت را به سایتش اضافه کند تا کاربرانی که غذایی را سفارش میدهند بتوانند نظر خودشان را راجع به غذا بگویند تا کاربران بعدی بتوانند بهتر و راحت تر غذای خودشان را انتخاب کنند.
این سایت سفارش آنلاین آنقدر سرش گرم تحویل غذاها و رسیدگی به سفارشهای مشتریهایش هست که وقت نمیکند این قابلیت را به سایتش اضافه کند و از شما میخواهد که در این کار کمکش کنید. سورس کد پروژه را میتوانید از [اینجا](https://quera.ir/qbox/download/4Xq3u9nu7P/order_food.zip) دانلود کنید.
همانطور که مشاهده میکنید، در فایل `models.py` یک مدل به نام `Food` وجود دارد که شامل سه فیلد `name`، `price` و `description` است که به ترتیب نام، قیمت و توضیحات یک غذا را نشان میدهند.
همچنین یک فایل template نیز نوشته شده است که توسط view ی `menu_view` رندر شده و لیست همه غذاها را نشان میدهد. که این view با استفاده از آدرس (url) `/menu` صدا زده میشود.
شما باید در این صفحه بخش کامنتها را به شکل زیر اضافه کنید:
+ زیر هر غذا لیست همه کامنتهای آن غذا را با فرمت زیر نشان دهید:
+ برای هر کامنت نام کسی که کامنت را گذاشته است، تاریخ ثبت کامنت و متن کامنت باید چاپ شود.
+ برای مثال یک کامنت بدین شکل است. (فرمت تاریخ باید **دقیقا** به این شکل باشد. با گذاشتن تاریخ در template، تاریخ به همین شکل به نمایش در میآید.)
```
Aug. 21, 2017, 1:41 p.m. - amirhosein
khyli khosh maze bood. mamooon :D
```
*نام و تاریخ لازم نیست حتما نسبت به هم بدین شکل باشند، یعنی میتوانید نام و تاریخ را در سطرهای جدایی نمایش دهید یا ...*
+ اگر کاربر لاگین نباشد نباید بتواند کامنتی بگذارد و بنابراین هیچ فرمی برای گذاشتن کامنت نباید نمایش یابد و به جای آن **باید** عبارت `"Please log in to leave a comment."` را در این صفحه نمایش دهید.
+ اگر کاربر لاگین باشد باید به ازای هر یک غذا در انتهای کامنتها یک فرم برای گذاشتن کامنت در نظر بگیرید. یعنی اگر n غذا داریم، n فرم نیز باید در صفحه باشد.
+ این فرمها فقط یک فیلد برای نوشتن کامنت و یک دکمه برای ثبت کامنت باید داشته باشند و میتوانند چندین فیلد hidden دیگر نیز به اختیار خود داشته باشند.
+ نویسنده پیام user name کاربر فعلی است و تاریخ و ساعت لحظه سابمیت شدن فرم برای به عنوان تاریخ آن کامنت در نظر گرفته میشود.
+ وقتی یکی از فرمها سابمیت شد بعد از ثبت شدن کامنت باید دوباره صفحهی `/menu` به نمایش درآید و کامنت ثبت شده در صفحه باشد.
+ در این لحظه بعد از ثبت کامنت یک پیام مبنی بر موفقیت آمیز بودن ثبت کامنت با متن `"your comment successfully submitted."` باید در صفحه به نمایش در بیاید که اگر صفحه دوباره refresh شود پیام نیز از صفحه حذف میشود.
+ فیلد کامنت در این فرم باید اجباری باشد و کسی نتواند کامنت با متن خالی بگذارد.
توجه کنید که اگر پاسخ شما تنها به بخشی از قسمتهای سوال پاسخ دهد، همان بخش از نمره را نیز دریافت میکنید.
### کتابخانهی استفاده شده
در این سوال شما برای انجام کارهای گفته شده ورژن 1.8.0 از کتابخانه `django-contrib-comments` را در اختیار دارید و باید از آن استفاده کنید. مستندات این کتابخانه در لینک زیر قابل مشاهده است:
[Django comments](http://django-contrib-comments.readthedocs.io/en/latest/)
### فایل آپلودی
فایلی که باید آپلود کنید یک فایل zip. است که درون آن یک پوشه `order_food` وجود دارد که شامل دو فایل `models.py` و `views.py` است و همچنین یک فایل به نام `menu.html` که درون دایرکتوری `order_food/templates/order_food`قرار دارد. توجه کنید در صورتی که فایلهای اضافی ارسال کنید، حذف خواهند شد. ساختار فایلهای ارسالی باید به شکل زیر باشد.
توجه کنید که شما باید تنها فایل `menu.html` را تغییر دهید.
```
<Your-zip-name>.zip
└── order_food
├── models.py
├── templates
│ └── order_food
│ └── menu.html
└── views.py
```
غذا چطور بود؟
+ این سوال سیستم داوری ندارد و پس از مسابقه توسط تیم شرکت «تومن» بررسی میشود.
+ برای استخدام در این شرکت بسیار توصیه میشود این سوال را حل کنید، اما تاثیری روی رتبهی شما و جایزهی مسابقه ندارد.
---
در این سوال توانایی مدلسازی شما سنجیده میشود. در پروژهی زیر مدلسازی یک سامانه پرداخت آنلاین را میبینید.
```python
from django.db import models
class User(models.Model):
username = models.CharField(max_length=100, unique=True)
balance = models.PositiveIntegerField(default=0)
class Merchant(models.Model):
balance = models.IntegerField(default=0)
class Transaction(models.Model):
TYPE_CHOICES = (
(1, 'shopping'),
(2, 'subscription'),
(3, 'rent'),
(4, 'bill'),
(5, 'loan'),
(6, 'donation')
)
type = models.IntegerField(db_index=True, choices=TYPE_CHOICES)
payer = models.ForeignKey('User', related_name='payments', on_delete=models.PROTECT)
payee = models.ForeignKey('Merchant', related_name='receipts', on_delete=models.PROTECT)
amount = models.PositiveIntegerField()
```
[لینک دانلود فایل کد](https://quera.ir/qbox/download/khVg5v5PMX/quera_question.py)
در سامانهی توصیف شده تعدادی کاربر خریدار و تعدادی فروشنده وجود دارد، و تعدادی تراکنش که بین یک فروشنده و یک خریدار صورت میگیرد. اولین کاری که باید بکنید این است که با مشاهدهی مدل، اهداف بخشهای آن را خودتان متوجه شوید!
حال ما میخواهیم قابلیت امکان تخفیف را به نوع `bill` از تراکنش در سامانه اضافه کنیم. یعنی تنها تراکنشهایی که از نوع `bill` هستند قرار است بتوانند تخفیف داشته باشند، و در نهایت قرار است این امکان کاملا پیادهسازی شود و در سامانه استفاده شود.
شما باید مدلهای سامانهی جدید را طراحی کنید. برای این طراحی برای هر تغییری کاملا آزاد هستید؛ شما میتوانید مدلهای فعلی را تغییر دهید و همچنین شما میتوانید هر چند مدلی که خواستید به آن اضافه کنید.
در کنار تغییراتی که میدهید، در صورت نیاز، توضیحی راجع به دلیل آن نیز بنویسید. این توضیحات را هم در کنار کدتان ارسال کنید. میتوانید این توضیحات را در کد بصورت کامنت بنویسید، و یا در فایلی جداگانه قرار دهید.
در نهایت یک فایل *zip* که شامل موارد گفته شده است برای این سوال ارسال کنید. برای ساختار فایل *zip* ارسالی و موارد داخل آن نیز محدودیتی ندارید.