همه چی از uber شروع شد. ایده‌ی خوبی که رانندگان را به مسافران وصل می‌کرد و هر کسی هر جایی بود به سرعت می‌توانست برای خودش تاکسی درخواست دهد. مدتی نگذشت که برنامه‌نویس‌های داخل کشور عزیزمان هم از این سرویس ایده گرفتند و شروع به پیاده‌سازی مشابه آن در ایران کردند. در حال حاضر چندین سرویس درخواست آنلاین تاکسی وجود دارد که در تهران و چند شهر دیگر مشغول سرویس‌دهی به مسافرین هستند و روز به روز هم گسترش بیشتری می‌یابند و اشتغال‌زایی زیادی را نیز به وجود آورده‌اند. حالا با توجه به بازار داغ این سرویس ما نیز می‌خواهیم یک سرویس مشابه ایجاد کنیم. اسمش را هم cabin گذاشته‌ایم.

پروژه اولیه

پروژه اولیه را از این لینک دانلود کنید. ساختار این پروژه به شرح زیر است:

cabin
├─── manage.py
├─── requirements.txt
│
├─── cabin
│   ├─── admin.py
│   ├─── apps.py
│   ├─── models.py
│   ├───  > queries.py < 
│   ├─── tests.py
│   ├─── urls.py
│   ├─── views.py
│   ├─── __init__.py
│   │
│   ├─── fixtures
│   │   └─── sample_test_fixture.json
│   │
│   └─── migrations
│        ├── 0001_initial.py
│        └─── __init__.py
│
├───challenge
│   ├─── settings.py
│   ├─── urls.py
│   ├─── wsgi.py
│   └─── __init__.py
│
└───tests
    ├─── testsample.py
    └─── __init__.py
Plain text

همانطور که در فایل‌ها می‌بینید یک 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: صاحب خودرو که یک راننده (از جنس مدل Driver) است.
  • 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 برگردانید.
{'income': value }
JSON

۲. کل مبلغ پرداخت‌شده توسط مشتری با id برابر با x

{'payment_sum': value }
JSON

۳. تعداد راننده‌هایی که حداقل یک ماشین کلاس A دارند.

  • در این سوال باید .count() از QuerySet مربوطه را بازگرانید که نتیجه یک عدد خواهد بود.

۴. لیست درخواست‌های سفرِ در انتظار (یعنی درخواست‌هایی که به هیچ سفری وصل نباشد)

  • ترتیب این لیست اهمیت ندارد.

۵. لیست مسافرانی که مجموع مبلغ سفرهایشان بیشتر یا مساوی با t تومان است.

  • ترتیب این لیست اهمیت ندارد.

۶. اکانتِ راننده‌ای که بیشترین تعداد ماشین را دارد. اگر تعداد ماشین‌ها یکسان بود، راننده‌ای را بدهید که نام خانوادگی‌اش از نظر الفبایی کوچکتر است.

  • در این سوال باید یک شیء از نوع Account بازگرانید که نتیجه مانند زیر خواهد بود:
<Account: Account object>
JSON

۷. لیست همه مسافرانی که حداقل یک سفر با ماشین کلاس A داشته‌اند به همراه یک ستون اضافه با نام n که تعداد سفرهایی که هر مسافر با ماشین کلاس A داشته است را نشان می‌دهد.

  • ترتیب این لیست اهمیت ندارد.

۸. لیست ایمیل رانندگانی که حداقل یک ماشین با مدل x (توجه کنید که مدل با نوع متفاوت است!) یا به بالا دارند.

  • ترتیب این لیست اهمیت ندارد.
  • خروجی نمونه:
<QuerySet [{'account__email': 'linda180@gmail.com'}, {'account__email': 'jacqueline859@gmail.com'}, {'account__email': 'benjamin780@gmail.com'},.....]>
Plain text

۹. لیست همه راننده‌ها و یک ستون اضافه شده به آن به نام n که نشان‌دهنده تعداد سفرهای هر راننده است.

  • ترتیب این لیست اهمیت ندارد.

۱۰. لیست اسم‌های کوچک همه راننده‌ها و تعداد سفرهایی (n) که راننده با آن آسم انجام داده است.

  • بعضی راننده‌ها اسم‌های یکسانی دارند.
    • برای مثال اگر دو راننده مختلف با اسم jack وجود داشته باشند که هر کدام ۵ سفر انجام داده‌باشند، در لیست زیر فقط یک بار اسم jack با ۱۰ سفر می‌آید.
  • ترتیب این لیست اهمیت ندارد.
  • خروجی نمونه:
<QuerySet [{'n': 41, 'account__first_name': 'aaron'}, {'n': 44, 'account__first_name': 'adam'}, {'n': 19, 'account__first_name': 'alan'},.....]>
Plain text

۱۱. لیست رانندگانی که حداقل یک ماشین با رنگ c (مثلا White) که مدلِ همان ماشین، n (مثلا ۹۰) یا به بالا باشد (توجه کنید که مدل با نوع متفاوت است!)، دارند.

  • در این لیست نباید راننده‌ی تکراری وجود داشته باشد.
  • ترتیب این لیست اهمیت ندارد.

۱۲. لیست رانندگانی که حداقل یک ماشین با رنگ c و یک ماشین مدل n یا به بالا (توجه کنید که مدل با نوع متفاوت است!) دارند.

  • در این لیست نباید راننده‌ی تکراری وجود داشته باشد.
  • لزوما این دو ماشین یکسان نیست. ولی برای رنگ و مدل باید حداقل یک ماشین با شرایط گفته‌شده برای هر کدام وجود داشته باشد.
  • ترتیب این لیست اهمیت ندارد.

۱۳. مجموع طول سفرهایی که در آن اسم راننده n (مثلا jack) و اسم مسافر m بوده است.

{'sum_duration': value }
JSON

زیرمسئله‌ها

امتیاز بخش
۵ query_1
۵ query_2
۵ query_3
۵ query_4
۵ query_5
۵ query_6
۱۰ query_7
۱۰ query_8
۱۰ query_9
۱۰ query_10
۱۰ query_11
۱۰ query_12
۱۰ query_13

امکانات اضافه

در صورتی که علاقمندید که خودتان به صورت دستی کوئری‌های خود را امتحان کنید و از درستی آن‌ها اطمینان حاصل کنید، یا اینکه به بررسی بیشتر از این تمرین بپردازید، برای راحتی بیشتر شما، فایل‌های مایگریشن‌ها ساخته شده‌اند و شما کافیست جهت ایجاد پایگاه‌داده، یک بار دستور migrate را اجرا کنید.

علاوه‌بر این، یک سری داده‌ی از پیش آماده شده، فراهم شده که بعد از اجرای دستور migrate، می‌توانید آن‌ها را وارد پایگاه‌داده‌ی پروژه‌ی خود کنید. به این منظور، دستور زیر را اجرا کنید. می‌توانید از این داده‌ها به جهت تست کردن کوئری‌های خود استفاده کنید.

۱. ایجاد پایگاه‌داده

python manage.py migrate
Shell
terminal

۲. وارد کردن داده‌های از پیش آماده شده (fixture)

python manage.py loaddata cabin/fixtures/sample_test_fixture.json
Shell
terminal

در صورتی که علاقمند به تست نیستید، نیازی به ایجاد پایگاه‌داده و وارد کردن داده‌های آزمایشی نیست، و تنها کافیست که در فایل queries.py کوئری‌های خود را بنویسید و از کوئرا جهت امتحان کردن درستی کوئری‌هایتان استفاده کنید.

تست نمونه

در فایل‌های اولیه‌ای که دانلود کردید یکسری داده اولیه به عنوان نمونه قرار داده شده است. همچنین ۳ تست نمونه برای ۳ پرس‌وجو اول بر اساس داده‌های اولیه قرار داده شده است که می‌توانید قبل از فرستادن سوال در سایت، این تست‌ها را ببینید تا با نحوه داوری ما آشنا شوید و از پاسخ خود اطمینان حاصل نمایید.

تست‌ها را می‌توانید با دستور زیر اجرا کنید:

python manage.py test
Shell
terminal

نکات

  • یک فایل به نام queries.py وجود دارد که برای هر سوال یک تابع در نظر گرفته شده است. شما باید کدهای خود را در این فایل بنویسید و QuerySet مربوطه را بازگردانید.
  • برای نمونه تابع query_0 در پاسخ به پرس و جویِ «لیست همه‌ی رانندگانی که رتبه‌ی آنها بیشتر از x است.» کامل شده است که شما نیز باید مشابه همین تابع بقیه توابع را کامل کنید.
def query_0(x):
    q = Driver.objects.filter(rating__gt=x)
    return q
Python
queries.py
  • در سوالاتی که در صورت سوال مقداری به صورت متغیر ذکر شده است (مانند x در مثال بالا)، متغیر مورد نظر در آرگومان‌های ورودی تابع درنظر گرفته شده است. شما خود نباید آرگومان‌های ورودی تابع را تغییر دهید.
  • در تمام سوالات به جز سوالاتی که خروجی نمونه برای آنها مشخص شده است، همان‌طور که ذکر شد، خروجی شما یک شئ از نوع QuerySet با المان‌هایی از جنس گفته‌شده در اول سوال باید باشد. یعنی در واقع خود query را return کنید.
  • برای مثال اگر سوال گفته باشد «لیست ماشین هایی که....» خروجی شما به شکل زیر باید باشد:
<QuerySet [<Car: Car object>, <Car: Car object>,.....]>
Plain text
  • در سوالات دیگر نیز که خروجی مشخص شده است، باز نتیجه یک QuerySet است ولی شامل همه فیلدهای مدل مورد نظر نمی‌شود و فقط فیلد‌های خواسته‌شده با نام خواسته‌شده باید در آن قرار داشته باشد.
  • شما تنها مجوز ایجاد تغییرات در فایل‌ cabin/queries.py را دارید و تمامی تغییرات دیگر شما در فایل‌های پروژه نادیده گرفته خواهند شد.
  • فراموش نکنید که می‌توانید با مطالعه‌ی testsample.py با روش تست کردن کوئری‌ها آشنا شوید.

نحوه ارسال

یک فایل ZIP حاوی همه‌ی فایل‌های پروژه، آپلود کنید. نام فایل ZIP اهمیتی ندارد.


ارسال پاسخ برای این سؤال
فایلی انتخاب نشده است.