میخواهیم برنامهای بنویسیم تا بتوانیم با فایل نمرات دانشجویان کار کرده
و کارهایی که پیش از این توسط مسئولین آموزش به صورت دستی بر روی این فایلها
انجام میشد را خودکار کنیم. هر سطر از این فایل دارای سه بخش است که با
کاراکتر فاصله (`" "`) از هم جدا شدهاند. این سه بخش به ترتیب عبارتند از:
1. شماره دانشجویی (عدد صحیح)
2. کد درس (عدد صحیح)
3. نمره (عدد اعشاری)
یعنی هر سطر از این فایل مشخص میکند که یک دانشجو در یک درس چه نمرهای را
گرفته است.
چند نیاز اساسی در رابطه با این فایلها وجود دارد:
+ میخواهیم بتوانیم یک سطر دلخواه از این فایل را در قالب یک شئ از جنس `Grade` بخوانیم.
+ میخواهیم بتوانیم یک شئ از جنس `Grade` را به صورت یک سطر از فایل نمرات و در انتهای فایل ذخیره کنیم.
+ میخواهیم بتوانیم معدل دانشجویان در یک درس خاص را محاسبه کنیم.
+ میخواهیم بتوانیم معدل یک دانشجو را محاسبه کنیم.
# جزئیات
یک کلاس به نام `Grade` شامل سه خصوصیت با اسامی زیر بنویسید.
+ شماره دانشجویی: `student_id`
+ کد درس: `course_code`
+ نمره: `score`
کلاس شما باید دارای متد سازندهای باشد که این سه خصوصیت را به همین ترتیب دریافت و مقداردهی کند.
با توجه به نیازمندیهایی که در بالا گفته شد، یک کلاس با نام `CourseUtil`
تعریف کنید که همه متدهای جدول زیر را طبق رفتار توضیح داده شده پیادهسازی کند.
| رفتار |خروجی| متد |
|:------------------:|:-------:|:-----------:|
|آدرس فایل نمرات به ورودی این متد داده میشود.|`-`| `set_file(address)`|
|یک شماره خط از فایل را در ورودی میگیرد و اطلاعات موجود در آن خط از فایل را در قالب یک شئ `Grade` برمیگرداند.|`Grade`| `load(line_number)`|
|یک شئ `Grade` در ورودی میگیرد و طبق فرمت مورد نظر، آن را در انتهای فایل اضافه میکند.|`-`|`save(grade)`|
|میانگین نمرات دانشجویان در درس با کد `course_code` را برمیگرداند. |`float`|`calc_course_average(course_code)`|
|میانگین نمرات دانشجو با شماره دانشجویی `student_id` در درسهای مختلف را برمیگرداند.|`float`|`calc_student_average(student_id)`|
|تعداد کل نمرات موجود در فایل نمرات را برمیگرداند.|`int`|`count()`|
# نکات
+ آدرس فایل با کمک متد `set_file` در اختیار کلاس قرار داده میشود. شما باید خودتان فایل را به نحوه دلخواه باز کنید.
+ در متد `load` اگر مقدار `line_number` بزرگتر از تعداد خطهای فایل بود، باید `None` برگردانید. شمارهی خطوط از ۱ شروع میشود.
+ متد `set_file` ممکن است چند بار فراخوانی شود که پس از هر فراخوانی، اطلاعات فایل جدید باید خوانده شود.
+ در فایل نمرات برای هر دانشجو در هر درس فقط یک نمره وجود دارد. بنابراین اگر برای دانشجو و درسی که نمره اش در فایل وجود دارد نمره جدیدی با متد `save` ثبت کنیم، نباید در فایل تغییری ایجاد شود.
+ در انتهای فایل `\n` وجود ندارد. شما نیز باید طوری فایل را تغییر دهید که هیچ گاه در انتهای فایل `\n` وجود نداشته باشد.
+ تضمین میشود که در هنگام محاسبه میانگینها شماره دانشجویی یا شماره درس داده شده در فایل موجود است.
در کد زیر یک فایل شامل دو سطر به عنوان ورودی داده شده است.
```
util = CourseUtil()
util.set_file(file)
print(util.count())
grade = Grade(445612,1234,12)
util.save(grade)
print(util.count())
util.set_file(file)
print(util.count())
```
خروجی زیر مورد انتظار است:
```
2
3
3
```
#### آنچه باید آپلود کنید:
یک فایل Zip شامل یک فایل به نام `source.py` که کلاسهای `Grade` و `CourseUtil` در آن قرار دارد آپلود کنید.
منبع سؤال: مسابقات جاواکاپ
محمد، مهدی و پارسا به مسابقات ACM جهانی راهیافتهاند روز مسابقه هر تیم باید نام تیم خود را در فایل دیتابیس sqlite اضافه کند ما باید کتابخانهای بنویسیم که کار را برای ارتباط با دیتابیس برای مهدی و دوستان ساده کند. این کد قرار است شبیه به یک [ORM](https://en.wikipedia.org/wiki/Object-relational_mapping) کار کند.
در این سوال تنها کتابخانه sqlalchemy نصب شده است که میتوانید از آن استفاده کنید.
فایل اولیه را از [این لینک](http://bayanbox.ir/download/6840354036702869912/ORM-project.zip) دریافت کنید. تست نمونه در فایل قرار داده شده است. کد شما باید به صورت زیر باشد.
```python
from exceptions import *
class ORM:
def __init__(self, db_path):
self.db_path = db_path
self.create_database_if_not_exist()
def create_database_if_not_exist(self):
pass
def create_table(self, table_path, table_name):
pass
def add_value(self, table_path, table_name, **values):
pass
def add_values(self, table_path, table_name, values):
pass
def remove_value(self, table_path, table_name, **values):
pass
def remove_values(self, table_path, table_name, values):
pass
def get_values(self, table_path, table_name, **filters):
pass
```
۱. تابع `create_database_if_not_exist` در صورتی که فایل پایگاه داده تاکنون ساخته نشده آن را در آدرس `db_path` میسازد. نمونه `db_path` که به پوشه databases و پایگاه first.sqlite3 اشاره میکند (پوشه databases از قبل باید وجود داشته باشد) :
`db_path = r'databases/first.sqlite3''`
۲. تابع `create_table` قرار است مسیر تعریف `table` و نام آنرا دریافت کند و جدول را در پایگاه داده بسازد.
نحوه تعریف جدول در پایگاه داده به صورت زیر است.
```python
# path : tables/users.py
from sqlalchemy import Integer, Column, String
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
class User(Base):
__tablename__ = 'user'
name = Column(String, primary_key=True)
family = Column(String, primary_key=True)
likes = Column(Integer)
order_fields = ['name', 'family']
def to_json(self):
return {
'name': self.name,
'family': self.family,
'likes': self.likes
}
```
در این صورت تابع را به صورت `create_table('tables.user', 'User')` صدا میزنیم. در صورت موجود بودن جدول در پایگاه داده، استثنا `TableExistsException` را باید `raise` کنید.
۳. تابع `add_value` مقدار جدید را میگیرد و در جدول مربوطه ذخیره میکند نحوه صدا زدن این تابع به صورت
`add_value('tables.user', 'User', name='mahdi', family='shokri', likes=3)`
است. در صورت موجود بودن مقدار از قبل در جدول باید استثنا `ValueExistException` و در صورت هرگونه مشکل دیگر باید استثنا `AddValueException` را `raise` کنیم.
۴. تابع `add_values` مقادیر جدید را میگیرد و در جدول مربوطه ذخیره میکند. نحوه صدا زدن این تابع به صورت
`add_values('tables.user', 'User', [{'name': 'mahdi', 'likes': 3, 'family': 'shokri' }])`
است. به ازای هر مورد در آرایه آنرا به جدول اضافه میکند. توجه کنید که یا همه موارد اضافه شوند یا در صورت هرگونه مشکل برای هرکدام از موارد آرایه باید استثنا `AddValuesException` را `raise` کنیم و پایگاه داده را به حالت قبل از این دستور، `rollback` کنیم.
۵. تابع `remove_value` مقداری را میگیرد و بر اساس آرگومانها موارد را فیلتر میکند و حذف مینماید. مثلا
`add_value('tables.user', 'User', name='mahdi')`
تمام افرادی که نامشان `mahdi` است را حذف میکند. در صورت نبودن سطری برای حذف شدن در جدول یا هرگونه مشکل دیگر باید استثنا `RemoveValueException` را `raise` کند.
۶. تابع `remove_values` آرایه ای از فیلترها میگیرد و به ازای هر کدام از فیلترها موارد مربوط به آن فیلتر را که در جدول مطابقت دارند حذف میکند.
`add_value('tables.user', 'User', [{'name': 'mahdi'}, {family': 'mohammadi'}])`
به ازای هرکدام از موارد در آرایه حداقل باید یک سطر برای حذف شدن وجود داشته باشد در غیر این صورت استثنا `RemoveValuesException` بازگردانده شود.
۷. تابع `get_values` مقادیر فیلتر را دریافت میکند و نتیجهای را به صورت `json` باز میگرداند. مثلا اگر تابع
`get_values('tables.user', 'User', name='mahdi')`
را صدا بزنیم تمام سطرهای جدول که `name` در آنها `mahdi` باشد را برمیگرداند. توجه کنید که ترتیب موارد در خروجی `json` باید بر اساس `order_fields` در تعریف جدول (در اینجا `User`) باشد.
```json
[
{
'name': 'mahdi',
'family': 'shokri',
'likes': 4
},
{
'name': 'mahdi',
'family': 'sorkhi',
'likes': 2
}
]
```
+ نکته: هر جدولی که برای تست به شما کد شما داده شود، حتما دارای تابع `to_json()` است و نیازی نیست شما آن را تبدیل به json کنید.
کد ارسالی شما باید به صورت زیر در ریشه فایل `zip` باشد. حتما قبل از ارسال تستهای نمونه را اجرا کنید.
```
<your-zip-name>.zip
└── orm.py
```
Python - محمد، مهدی و پارسا
میخواهیم یک سایت برای خودکار کردن فرایند فروش بلیتهای سینما بنویسیم.
در این سایت امکان مشاهده فیلمهای در حال اکران وجود دارد.
کاربران میتوانند عضو سایت شوند و پس از ورود به سایت
برای هر فیلم صندلی موردنظر را رزرو کند.
بخشی از این پروژه نوشته شده است. از شما میخواهیم این پروژه را تکمیل کنید.
# پروژه اولیه
پروژه اولیه را از [اینجا](http://bayanbox.ir/download/5545408568741586764/cinema.zip) دانلود کنید. ساختار این پروژه به شرح زیر است:
```
cinema
├── app
│ ├── migrations
│ │ ├── __init__.py
│ │ └── 0001_initial.py
│ ├── templates
│ │ └── app
│ │ ├── movies.html
│ │ └── seats.html
│ ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── models.py
│ ├── urls.py
│ └── views.py
├── Cinema
│ ├── __init__.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
├── templates
│ └── registration
│ ├── login.html
│ └── signup.html
├── manage.py
└── requirements.txt
```
# جزئیات
در این سؤال تنها لازم است تغییراتی در `app/views.py` و `app/fixtures` ایجاد کنید.
در فایل `models.py` سه مدل به شرح زیر وجود دارد:
۱. مدل `Movie` شامل فیلدهای زیر:
* `title`: نام فیلم
* `release_year`: سال انتشار فیلم
* `play_time`: زمان اکران فیلم در سالن
۲. مدل `Seat` شامل فیلد زیر:
* `number`: شماره صندلی
۳. مدل `Ticket`شامل فیلدهای زیر:
* `movie`: فیلمی که این بلیت برای آن فروخته شده است
* `user`: کاربری که این بلیت را خریده است
* `seat`: صندلی مربوط به این بلیت
* `date_bought`: تاریخی که بلیت خریده شده است
قرار است همه صندلیهای سالن و لیست فیلمها در ابتدا با استفاده از fixture
به پایگاه داده اضافه شود. سپس به ازای هر بلیتی که فروخته میشود
یک شیٔ از مدل `Ticket` ساخته میشود.
مواردی که باید انجام دهید:
### ۱. نوشتن fixture
از شما میخواهیم دو فایل *fixture* با نامهای
`movies` و `seats`
در مسیر `app/fixtures`
بنویسید. این *fixture* ها را میتوانید به فرمت
`JSON` یا `YAML`
بنویسید.
+ فایل `movies` باید شامل دادههای زیر باشد.
زمان اکران را به صورت naive (بدون TimeZone) تعریف کنید.
| id | نام فیلم | سال انتشار | تاریخ اکران | ساعت اکران |
|:---:|:----------:|:-------------:|:-------------:|:-------------------:|
| 1 | Children of heaven | 1997 | 2018/4/20 | 22:00 |
| 2 | About Elly | 2009 | 2018/4/20 | 20:00 |
| 3 | A separation | 2011 | 2018/4/22 | 18:00 |
| 4 | The salesman | 2016 | 2018/4/21 | 18:00 |
| 5 | The Elephant king | 2017 | 2018/4/21 | 20:00 |
+ فایل `seats` نیز باید شامل ۱۰ صندلی با `id` های ۱ تا ۱۰
و با شماره صندلیهای ۳۱ تا ۴۰ (به ترتیب `id` ها) باشد.
### ۲. نمایش صندلیها
در این قسمت باید view نمایش صندلیها (`list_seats`) را به گونهای تغییر دهید
که فقط صندلیهایی که برای فیلم موردنظر رزرو نشدهاند نمایش داده شوند.
### ۳. رزرو صندلی
با توجه به توضیحات زیر، view ها را تکمیل کنید.
برای رزرو صندلی، کاربر مراحل زیر را انجام میدهد:
+ ابتدا از آدرس `/movie` بازدید میکند که لیست فیلمهایی که در حال اکران هستند
را نمایش میدهد. سپس روی فیلم مورد نظر خود کلیک کرده و صفحهی بعدی صندلیهای رزرو
نشده برای آن فیلم را نمایش میدهد. تا این مرحله کاربر نیازی به login بودن ندارد.
+ وقتی کاربر روی یکی از صندلیها کلیک کرد:
+ اگر کاربر login است، صندلی برای کاربر
رزرو شده و دوباره به صفحهی صندلیهای همان فیلم *redirect* میشود تا
بتواند صندلیهای دیگری را نیز رزرو کند.
+ اگر کاربر login نیست،
به صفحهی *login* هدایت میشود و پس از وارد شدن به سایت،
بلافاصله به صفحهی قبلی (صفحه لیست صندلیها) *redirect* میشود،
بدون این که صندلی رزرو شود.
+ در صفحهی *login* اگر کاربر روی لینک *signup* کلیک کرد و در سایت
عضو شد، باید بلافاصله پس از عضویت به طور خودکار در سایت login شود
و به صفحه لیست فیلمها *redirect* شود.
### ۴. گزارش گیری سایت
در این قسمت شما باید view مربوط به آدرس `stats` را به نحوی کامل کنید
که در پاسخ برای همه صندلیهای که حداقل
برای یک فیلم رزرو شدهاند (به ترتیب `id` صندلی)،
یک خروجی JSON به شکل زیر بازگردد:
```json
[{"seat__number": 31, "total": 3}, {"seat__number": 32, "total": 1}, ... ]
```
+ مقدار *total*، تعداد رزروهای صندلی مشخص شده است.
+ این *view* تنها باید برای مدیران (superuser ها) فعال باشد و برای سایر افراد
خطای ۴۰۳ (Forbidden) برگرداند.
# نکات
+ شما تنها مجاز به تغییر در `app/views.py` و `app/fixtures` هستید.
اگر تغییری در سایر فایلها ایجاد کنید، این تغییرات نادیده گرفته خواهد شد.
+ پس از اعمال تغییرات، کل پروژه را Zip کرده و ارسال کنید.
+ نام فایل Zip اهمیت ندارد.
همه چی از uber شروع شد. ایده ی خوبی که رانندگان را به مسافران وصل میکرد و هر کسی هر جایی بود به سرعت میتوانست برای خودش تاکسی درخواست دهد. مدتی نگذشت که برنامهنویس های داخل کشور عزیزمان هم از این سرویس ایده گرفتند و شروع به پیاده سازی مشابه آن در ایران کردند. در حال حاضر چندین سرویس درخواست آنلاین تاکسی وجود دارد که در تهران و چند شهر دیگر مشغول سرویس دهی به مسافرین هستند و روز به روز هم گسترش بیشتری میابند و اشتغالزایی زیادی را نیز به وجود آوردهاند. حالا با توجه به بازار داغ این سرویس ما نیز میخواهیم یک سرویس مشابه ایجاد کنیم. اسمش هم `cabin` گذاشتهایم. شما میتوانید پروژه کابین رو از [اینجا](http://bayanbox.ir/download/6519668623165691239/cabin.zip) دانلود کنید.
همانطور که در فایل ها میبینید یک app به نام cabin وجو دارد. در فایل models.py هشت مدل به شرح زیر وجود دارد:
+ Account: اکانت که به یک مدل دیگر اعم از راننده یا مسافر یا مدیر سیستم وصل است و شامل فیلد های زیر است
+ first_name: نام شخص
+ last_name: نام خانوادگی شخص
+ email: ایمیل شخص
+ phone: شماره تلفن شخص
+ password: پسورد شخص
+ Admin: مدیر سیستم که دسترسی هایی خاصی به سیستم دارد
+ account: اکانت ادمین که اطلاعات او را نگه میدارد
+ Rider: مسافر
+ account: اکانت مسافر که اطلاعات او را نگه میدارد
+ x: طول جغرافیایی موقعیت مسافر
+ y: عرض جغرافیایی موقعیت مسافر
+ rating: امتیاز مسافر
+ Driver: راننده
+ account: اکانت راننده که اطلاعات او را نگه میدارد
+ x: طول جغرافیایی موقعیت راننده
+ y: عرض جغرافیایی موقعیت راننده
+ rating: امتیاز راننده
+ active: آماده به کار بودن با نبود راننده را نشان میدهد
+ Car: خودرو
+ owner: صاحب خودرو که یک راننده است
+ car_type: نوع کلاس خودرو
+ model: سال تولید خودرو
+ color: رنگ خودرو
+ RideRequest: درخواست سفر
+ rider: مسافر درخواست دهنده
+ x: طول جغرافیایی نقطه درخواست
+ y: عرض جغرافیایی نقطه درخواست
+ car_type: کلاس خودرو درخواست شده
+ Ride: سفر
+ pickup_time: (زمان شروع سفر(سوار کردن مسافر
+ dropoff_time: زمان پایان سفر
+ *دو زمان بالا از نوع عدد صحیح و نشاندهنده تعداد ثانیه های گذشته از زمان تاسیس شرکت می باشند.*
+ request: درخواست سفری که این سفر به آن مربوط میشود
+ car: خودرویی که این سفر با آن انجام شده است
+ rider_rating: امتیازی که راننده به مسافر داده است
+ driver_rating: امتیازی که مسافر به راننده داده است
+ Payment: پرداخت
+ ride: سفری که پرداخت برای آن انجام شده است
+ amount: مبلغ پرداخت شده برحسب تومان
+ status: وضعیت پرداخت
حال از شما میخواهیم پرس و جو (query) های زیر را روی مدل های بالا بنویسید.
**حتما قبل شروع نوشتن کد، تذکرات انتهای سوال را بخوانید!**
#### ۱. ورودی کل شرکت کابین (پولی که از طریق پرداخت وارد شرکت میشود)
در اینجا status تاثیری ندارد و نتیجه را میتوانید به صورت dict برگردانید.
```json
{'income': value }
```
#### ۲. کل مبلغ پرداخت شده توسط مشتری با id برابر با x
```json
{'payment_sum': value }
```
#### ۳. تعداد راننده هایی که حداقل یک ماشین کلاس A دارند.
+ در این سوال باید `.count()` از QuerySet مربوطه را بازگرانید که نتیجه یک عدد خواهد بود.
#### ۴. لیست درخواست های سفرِ در انتظار (یعنی درخواست هایی که به هیچ سفری وصل نباشد)
#### ۵. لیست مسافرانی که مجموع مبلغ سفر هایشان بیشتر یا مساوی با t تومان است.
#### ۶. اکانتِ راننده ای که بیشترین تعداد ماشین را دارد. اگر تعداد ماشین ها یکسان بود راننده ای را بدهید که نام خانوادگیاش از نظر الفبایی کوچکتر است.
+ در این سوال باید یک شیء از نوع Account بازگرانید که نتیجه مانند زیر خواهد بود:
```json
<Account: Account object>
```
#### ۷. لیست همه مسافرانی که حداقل یک سفر با ماشین کلاس A داشته اند به همراه یک ستون اضافه با نام `n` که تعداد سفر هایی که هر مسافر با ماشین کلاس A داشته است را نشان میدهد.
#### ۸. لیست ایمیل رانندگانی که حداقل یک ماشین با مدل x (توجه کنید که مدل با نوع متفاوت است!) یا به بالا دارند.
خروجی نمونه:
```
<QuerySet [{'account__email': 'linda180@gmail.com'}, {'account__email': 'jacqueline859@gmail.com'}, {'account__email': 'benjamin780@gmail.com'},.....]>
```
#### ۹. لیست **همه** راننده ها و یک ستون اضافه شده به آن به نام `n` که نشان دهنده تعداد سفر های هر راننده است.
#### ۱۰. لیست اسم های کوچک همه راننده ها و تعداد سفر هایی (`n`) که راننده با آن آسم انجام داده است.
+ *بعضی راننده ها اسم های یکسانی دارند*
+ برای مثال اگر دو راننده مختلف با اسم jack وجود داشته باشند که هر کدام ۵ سفر انجام داده باشند، در لیست زیر فقط یک بار اسم jack با ۱۰ سفر میآید.
خروجی نمونه:
```
<QuerySet [{'n': 41, 'account__first_name': 'aaron'}, {'n': 44, 'account__first_name': 'adam'}, {'n': 19, 'account__first_name': 'alan'},.....]>
```
#### ۱۱. لیست رانندگانی که حداقل یک ماشین با رنگ c (مثلا White) که مدلِ همان ماشین n (مثلا ۹۰) یا به بالا باشد (توجه کنید که مدل با نوع متفاوت است!)، دارند.
+ *در این لیست نباید رانندهی تکراری وجود داشته باشد.*
#### ۱۲. لیست رانندگانی که حداقل یک ماشین با رنگ c و یک ماشین مدل n یا به بالا(توجه کنید که مدل با نوع متفاوت است!) دارند.
+ *در این لیست نباید رانندهی تکراری وجود داشته باشد.*
+ *لزوما این دو ماشین یکسان نیست. ولی برای رنگ و مدل باید حداقل یک ماشین با شرایط گفته شده برای هر کدام وجود داشته باشد*
#### ۱۳. مجموع طول سفر هایی که در آن اسم راننده n (مثلا jack) و اسم مسافر m بوده است.
```json
{'sum_duration': value }
```
## **تذکرات:**
+ یک فایل به نام `queries.py` وجود دارد که برای هر سوال یک تابع در نظر گرفته شده است. شما کد های خود را باید در این فایل بنویسید و QuerySet مربوطه را بازگردانید.
+ برای نمونه تابع `query_0` در پاسخ به پرس و جویِ «لیست همه ی رانندگانی که رتبهی آنها بیشتر از x است.» کامل شده است که شما نیز باید مشابه همین تابع بقیه توابع را کامل کنید.
```python
def query_0(x):
q = Driver.objects.filter(rating__gt=x)
return q
```
+ در سوالاتی که در صورت سوال مقداری به صورت متغییر ذکر شده است(مانند x در مثال بالا)، متغییر مورد نظر در آرگومان های ورودی تابع در نظر گرفته شده است. شما خود نباید آرگومان های ورودی تابع را تغییر دهید.
+ در تمام سوالات به جز سوالات ۱ تا ۳ و ۶ و ۱۳ و سوالاتی که خروجی نمونه برای آنها مشخص شده است، همان طور که ذکر شد، خروجی شما یک شیء از نوع QuerySet با المان هایی از جنس گفته شده در اول سوال باید باشد. یعنی در واقع خود query را return کنید.
+ برای مثال اگر سوال گفته باشد «لیست ماشین هایی که....» خروجی شما به شکل زیر باید باشد:
```
<QuerySet [<Car: Car object>, <Car: Car object>,.....]>
```
+ در سوالات دیگر نیز که خروجی مشخص شده است، باز نتیجه یک QuerySet است ولی شامل همه فیلد های مدل مورد نظر نمیشود و فقط فیلد های خواسته شده با نام خواسته شده باید در آن قرار داشته باشد.
+ در هیچ کدام از پرس و جوی های خواسته شده ترتیب مهم نیست.
+ منظور از نام برای رانندگان و مسافران `first_name` است.
### فایل آپلودی
یک فایل zip. که درون آن یک پوشه `cabin` وجود دارد که شامل یک فایل `queries.py` است. توجه کنید در صورتی که فایلهای اضافی ارسال کنید، حذف خواهند شد.
```
<Your-zip-name>.zip
└── cabin
└── queries.py
```