سلام!
به مسابقه بَله کمپ دوآپس خوش آمدید.
به عنوان تمرین اول از شما میخواهیم تا اسکریپتی بنویسید که به تمام ورودیهای دریافتی سلام کند! یعنی پس از اجرا صرفا عبارت زیر را چاپ کند.
به علامتهای نگارشی و بزرگی و کوچکی توجه کنید. خروجی اسکریپت شما باید دقیقا برابر مقدار خواسته شده باشد.
برای دریافت پروژه اولیه این لینک را دانلود کنید. درون لینک ساختار فایلی زیر را مشاهده میکنید:
راهحل خود را درون فایل salam.sh
پیادهسازی کنید.
salam.sh
وارد نمایید.salam.sh
را آپلود کنید.سلیب فارغ از دنیا و آخرت در حال خوشگذرانی بود که ناگهان امین پیش او آمد و گفت که در پیامرسان بله خبر از گنجی به او رسیده. سلیب هم که برای مالی بادآورده جان میدهد، قبول کرد تا به دنبال گنج بگردد. برای این کار نیاز بود تا خود را با کشتی به جزیرهای برساند که در آنجا نقشهی گنج دفن شده بود.
سلیب مطمئن بود که سایتی برای خرید بلیط کشتی به ارزانترین حالت ممکن را قبلاً دیده و آن را بوکمارک کرده، اما نمیدانست که سایت را در کجای کدام مرورگر خود ذخیره کردهاست. او که به انجام ندادن کارهای خود عادت کرده، از شما خواسته تا اسکریپتی به زبان bash
برای او بنویسید تا تمامی بوکمارکهای تمامی مرورگرهای سلیب را به صورت markdown درون فایلی ذخیره کند. در ادامه به بیان جزئیات بیشتر مسئله میپردازیم.
برای دانلود پروژهی اولیه روی این لینک کلیک کنید.
در لپتاپ شخصی سلیب مرورگرهای chrome ،opera و operagx موجود هستند.
تمامی مرورگرها بوکمارکهای خود را در ساختاری مختص به خود درون فایل json
ذخیره میکنند. سلیب جهت آسانتر کردن کار شما، آدرس فایلهای مربوط به هر مرورگر را در فایلی با نام addresses.txt
در کنار اسکریپت شما ذخیره کردهاست. نمونه محتوای این فایل به شکل زیر است:
توجه داشته باشید ممکن است در آدرس کاراکترهای اسپیس ()، نقطه (
.
) و تیلدا (~
) موجود باشد، همچنین ترتیب مرورگرها درون فایل همواره ثابت نیست ولی همواره تمامی مرورگرها درون فایل موجود هستند.
اسکریپت شما باید آدرس و تایتل تمامی سایتهای بوکمارک موجود در هر یک از این مرورگرها را بیابد و سپس موارد تکراری موجود را حذف کند و در نهایت مطابق شکل زیر، موارد را درون فایلی با نام unique_bookmarks.md
ذخیره کند.
توجه داشته باشید ممکن است تایتل یا نام آدرسها با "
شروع یا تمام شوند. نیاز است تا شما این کاراکترها را از تایتل یا نام آدرس حذف کنید؛ اما اگر "
در وسط کلمه وجود داشت شما مجاز به حذف آن نیستید. مثلاً اسکریپت شما باید تایتل """"""""I love "IRAN" so much"
را به I love "IRAN" so much
تبدیل کند. همچنین دقت کنید که ممکن است در بیین تایتل آنها |
وجود داشته باشد؛ که این مورد هم باید حذف شود. برای مثال نام جامعه برنامهنویسان ایران | Quera
در فایل opera.json
باید به جامعه برنامهنویسان ایران Quera
تبدیل شود.
به علامتهای نگارشی و بزرگی و کوچکی توجه کنید. خروجی اسکریپت شما باید دقیقاً برابر مقدار خواستهشده باشد.
راهحل خود را درون فایل script.sh
موجود در پروژه اولیه، پیادهسازی کنید.
برای حل مسئله تنها مجاز به استفاده از دستور jq
برای پارس کردن فایلهای جیسون میباشید. داکیومنتیشن این دستور در این لینک قابل مشاهده است.
برای مثال در پروژهی اولیه، نمونهای از فایل ذخیرهشدهی بوکمارک در تمامی مرورگرهای مسئله موجود است. با اجرای اسکریپت شما، باید خروجی خواستهشده مشاهده شود:
همچنین محتوای فایل unique_bookmarks.md
هم باید بهصورت زیر باشد:
نیازی نیست ترتیب جدول خروجی مشابه ترتیب جدول در صورت سؤال باشد و به هر ترتیب دلخواهی مجاز به تشکیل جدول هستید. تعداد سطرهای خروجی اسکریپت شما باید دقیقاً برابر با تعداد سطرهای جدول بالا باشد.
script.sh
وارد نمایید.script.sh
را آپلود کنید.jq
ممکن است در توزیعهای مختلف لینوکس رفتار متفاوتی از خود نشان دهد؛ در نتیجه ترجیحا برای تست اسکریپت خود از سیستمعامل اوبونتو استفاده کنید.url
یا name
را در خود ذخیره کردهاند متفاوت است و شما باید به صورت بازگشتی چک کنید تا به پراپرتی url
یا name
برسید و آنها را استخراج کنید.سلیب پس از پیدا کردن سایت موردنظر در میان انبوهی از وبسایتهای خروجی مسئلهی قبل، به جزیره رسید و نقشهی گنج را پیدا کرد. پس از باز کردن نقشه، متوجه شد که نقشه به زبان عجیب و غریبی (احتمالاً عبری) نوشته شده و قادر به ترجمهی آن نیست. او که میدانست محال است بتواند نقشه را خودش ترجمه کند، به دنبال فردی با دانش عبری گشت. سلیب پس از پرسوجوهای فراوان با علی روبهرو شد که قبول کرد نقشه را برای او ترجمه کند؛ اما در ازای این کار، از او خواست تا تسک iteration فعلی او را برایش انجام دهد. سلیب هماکنون از شما درخواست انجام تسک پاکسازی و بهینه کردن ساختار ردیس شرکت علی را دارد.
برای دانلود پروژهی اولیه روی این لینک کلیک کنید.
برای انجام تسک شرکت علی نیاز به نوشتن یک اسکریپت به زبان bash
دارید و اسکریپت شما باید ۴ سطح از پاکسازی که در ادامهی مسئله با جزئیات بیشتری توضیحشان میدهیم را روی دیتای ردیس فعلیشان انجام دهد.
برای حل این تمرین نیاز به دانش کار با دستور redis-cli
را دارید که داکیومنتیشن آن را در این لینک میتوانید مطالعه کنید، همچنین جهت آشنایی با تمامی داده ساختارهای موجود در ردیس هم از این لینک کمک بگیرید.
در این سطح، نیاز است تمامی کلیدهایی از ردیس که شامل حداقل یک کاراکتر کوچک زبان انگلیسی است را به فرم بزرگ تغییر دهد. برای مثال اگر ردیس ما شامل کلیدهای زیر است:
پس از اجرای اسکریپت شما باید به شکل زیر تغییر کنند:
اسکریپت شما پس از تغییر هر کلید باید عبارتی به فرم زیر به فایل output.txt
اضافه کند.
برای مثال، پس از اجرای اسکریپت روی مثال بالا، محتوای فایل output.txt
شامل محتوای زیر باشد:
توجه داشته باشید تحت این عملیات پاکسازی مقدار هیچ کلیدی از ردیس نباید تغییر کند، یعنی پاکسازی شما نباید بههیچوجه باعث از دست رفتن دیتای موجود شود.
نکته پیرامون حفظ دیتا: ممکن است هنگامیکه شما کلید را بهصورت uppercase مینویسید، کلید جدید در ردیس وجود داشته باشد. در این صورت، تا زمانی که به کلیدی که در ردیسمان وجود نداشته باشد نرسیدهایم، عبارت DUPLICATE
را به انتهای کلید جدید اضافه میکنیم. برای مثال اگر ردیس ما شامل کلیدهای زیر باشد:
اسکریپت شما باید کلید redis-key1
را به REDIS-KEY1DUPLICATEDUPLICATE
تغییر دهد. یعنی پس از اجرای اسکریپت شما وضعیت کلیدهای ردیس مانند زیر خواهد بود:
و همچنین محتوای فایل output.txt
شامل محتوای زیر باشد:
در این سطح، نیاز است تا تمامی مقادیری از ردیس که بهصورت رشته هستند و با کاراکتر [
شروع و با کاراکتر ]
تمام میشوند را بهصورت لیست در ردیس ذخیره کند. همچنین پس از تغییر هر مقدار باید عبارتی به فرم زیر به فایل output.txt
اضافه کند.
برای مثال، اگر ردیس ما شامل مقداری مانند زیر است:
پس از اجرای اسکریپت شما باید مقدار کلید مذکور بهصورت دادهساختار لیست پیادهسازیشده در ردیس ذخیره شده باشد و بتوانیم مانند دستور زیر به محتوای آن دسترسی داشته باشیم:
برای مثال پس از اجرای اسکریپت روی مثال بالا، محتوای فایل output.txt
شامل محتوای زیر باشد:
توجه داشته باشید که اسکریپت شما باید ترتیب لیست را حفظ کند و تغییر در ترتیب مقدار مجاز نیست.
توجه داشته باشید که اگر درون مقدار کاراکتر گیومه ("
) وجود داشت، این کاراکتر باید از مقدار جدید حذف شود.
در این سطح، نیاز است تا تمامی مقادیری از ردیس که بهصورت رشته هستند و با کاراکتر (
شروع و با کاراکتر )
تمام میشوند را بهصورت ست در ردیس ذخیره کند. همچنین پس از تغییر هر مقدار باید عبارتی به فرم زیر به فایل output.txt
اضافه کند.
برای مثال اگر ردیس ما شامل مقداری مانند زیر است:
پس از اجرای اسکریپت شما باید مقدار کلید مذکور بهصورت دادهساختار ست پیادهسازیشده در ردیس ذخیره شده باشد و بتوانیم مانند دستور زیر به محتوای آن دسترسی داشته باشیم:
برای مثال، پس از اجرای اسکریپت روی مثال بالا، محتوای فایل output.txt
شامل محتوای زیر باشد:
توجه داشته باشید که اگر درون مقدار کاراکتر گیومه ("
) وجود داشت، این کاراکتر باید از مقدار جدید حذف شود.
در این سطح، نیاز است تمامی مقادیری از ردیس که بهصورت رشته هستند و با کاراکتر {
شروع و با کاراکتر }
تمام میشوند را بهصورت هش در ردیس ذخیره کند. همچنین پس از تغییر هر مقدار باید عبارتی به فرم زیر به فایل output.txt
اضافه کند.
برای مثال اگر ردیس ما شامل مقداری مانند زیر است:
پس از اجرای اسکریپت شما باید مقدار کلید مذکور بهصورت دادهساختار لیست پیادهسازیشده در ردیس ذخیره شده باشد و بتوانیم مانند دستور زیر به محتوای آن دسترسی داشته باشیم:
برای مثال پس از اجرای اسکریپت روی مثال بالا، محتوای فایل output.txt
شامل محتوای زیر باشد:
توجه داشته باشید که اسکریپت شما باید ترتیب لیست را حفظ کند و تغییر در ترتیب مقدار مجاز نیست.
توجه داشته باشید که اگر درون مقدار کاراکتر گیومه ("
) وجود داشت، این کاراکتر باید از مقدار جدید حذف شود.
برای اجرای نمونه نیاز به نصب داکر در سیستم خود دارید. نیازی نیست تا شما درون محتوای فایلهای داکر پروژه هیچ تغییری ایجاد کنید.
درون پروژه اولیه فایلهایی جهت تست اسکریپت شما تهیه شده که در ادامه نحوه کار با هرکدام را بررسی میکنیم. ابتدا اسکریپت خود را در فایل fixer.sh
پیادهسازی کنید. سپس با استفاده از دستور زیر کانتینرهای پروژه اولیه را بالا بیاورید:
پس از اتمام اجرای دستور بالا، دستور زیر را اجرا کنید. این دستور محتوای موجود در فایل redis-data.txt
را به درون ردیس در حال اجرا میریزد.
ساختار زیر به صورت "key":"value"
است:
یعنی مقدار کلید test1
برابر با 1
است.
پس از اتمام اجرای دستور بالا، باید اسکریپت خود را اجرا کنید. برای این کار از دستور زیر استفاده کنید:
حال باید اسکریپت شما اجرا شده باشد و در فایل output.txt
محتوای زیر قابل مشاهده باشد:
توجه داشته باشید که ترتیب خروجی برای سیستم داوری اهمیتی ندارد و تنها نیاز است تا تمامی موارد به هر ترتیب دلخواهی حتما در خروجی وجود داشته باشند.
پس از اتمام اجرای تست، حتما دستور زیر را اجرا کنید تا تمامی کانتینرها متوقف شوند:
"
از مقدارهایی که توسط اسکریپت شما تغییر میکنند، حذف شود.redis
وصل شوید.fixer.sh
وارد نمایید.fixer.sh
را آپلود کنید.سلیب پس از ترجمهی نقشه متوجه شد که گنج جایی در آبادی «بلهآباد» است که در پشت کوههای جزیره پنهان شدهاست. او سریعاً حرکت کرد و هنگامیکه به پشت کوههای «بلهآباد» رسید، متوجه شد که مردمان این آبادی، سامانهای شبیه سیستم بلاگ Medium ندارند. برای سلیب این موقعیت خوبی بود تا به جای جستوجوی شبانهروزی به دنبال گنج، از این طریق ثروتی کسب کند و بیخیال گنج بشود؛ پس درخواست پیادهسازی این سامانه را با مشخصاتی که در ادامه توضیح میدهیم، از شما دارد. :)
پروژهی اولیه را از این لینک دانلود کنید.
در این سؤال، ما با دو بخش کلی در ارتباط هستیم: بخش کاربران و بخش بلاگها. در ادامه جزئیات هر بخش را بیان میکنیم.
برای این بخش نیاز است تعدادی REST API شامل endpointهای زیر پیادهسازی شوند:
آدرس | عنوان |
---|---|
GET / |
بررسی up بودن سرویس |
POST /auth/signup/ |
ثبتنام |
POST /auth/login/ |
ورود به حساب کاربری |
POST /auth/logout/ |
خروج از حساب کاربری |
در این API هر کاربر باید یک توکن داشته باشد. این توکن برای هر کاربر ثابت است.
در همهی endpointها، پاسخ باید بهصورت JSON باشد.
اکیداً توصیه میگردد برای پیادهسازی بخش کاربر از JWT استفاده کنید.
اطلاعات ورودی بهصورت application/x-www-form-urlencoded
به endpointها ارسال میشوند.
پاسخ این endpoint باید بهصورت زیر باشد:
200
{"message":Welcome to Medium API}
سه پارامتر username
و password
و email
به این endpoint ارسال میشوند. درصورتیکه حداقل یکی از پارامترهای username
و password
ارسال نشده باشد یا برابر با رشتهی خالی باشد، پاسخ باید بهصورت زیر باشد:
هر دو پارامتر username
و password
خالی:
کد وضعیت: 400
بدنه:
پارامتر username
خالی:
کد وضعیت: 400
بدنه:
پارامتر password
خالی:
کد وضعیت: 400
بدنه:
اگر کاربری با نام کاربری واردشده، از قبل موجود باشد، پاسخ باید بهصورت زیر باشد:
کد وضعیت: 400
بدنه:
در غیر این صورت، کاربر باید ساخته شود، یک توکن یکتا برایش تولید شود و پاسخ بهصورت زیر باشد:
کد وضعیت: 201
بدنه:
دو پارامتر username
و password
باید به این endpoint ارسال شوند. درصورتیکه حداقل یکی از این پارامترها ارسال نشده باشد یا برابر با رشتهی خالی باشد، پاسخ باید بهصورت زیر باشد:
401
{"error": "Invalid credentials"}
اگر نام کاربری یا رمز عبور نادرست باشد، پاسخ باید بهصورت زیر باشد:
401
{"error": "Invalid credentials"}
در غیر این صورت، پاسخ باید بهصورت زیر باشد:
200
تنها پارامتر refresh
باید به این endpoint ارسال شود. درصورتیکه این پارامتر ارسال نشده باشد یا برابر با رشتهی خالی باشد یا حتی مقدار درستی نداشته باشد، پاسخ باید بهصورت زیر باشد:
400
{}
در غیر این صورت، پاسخ باید بهصورت زیر باشد:
205
{}
برای این بخش نیاز است تا تعدادی REST API شامل endpointهای زیر باید پیادهسازی شوند:
آدرس | عنوان |
---|---|
GET /blogs/ |
دریافت تمامی بلاگهای ثبت شده |
POST /blogs/create/ |
ایجاد بلاگ جدید |
PUT /blogs/<int:pk>/ |
آپدیت بلاگ |
DELETE /blogs/<int:pk>/ |
حذف بلاگ |
GET /blogs/<int:pk>/detail/ |
مشاهده بلاگ |
POST /blogs/<int:pk>/like/ |
لایک کردن بلاگ |
GET /blogs/analytics/ |
اوضاع کلی حساب نویسنده |
در همهی endpointها، پاسخ باید بهصورت JSON باشد.
اطلاعات ورودی بهصورت application/x-www-form-urlencoded
به endpointها ارسال میشوند.
این endpoint نیازمند authentication نیست.
نیازی به ارسال هیچ پارامتری به این endpoint نیست و در همهی حالات باید جواب برابر با مقدار زیر باشد:
200
بلاگهای برگرداندهشده باید به ترتیب زمان ثبت بلاگ باشند.
این endpoint نیازمند authentication است. در ریکوئست ارسالی، مقدار هدر Authorization
باید برابر با توکن کاربر باشد (توکن همواره همراه با Bearer
ارسال میشود.).
پارامتر title
و content
باید به این endpoint ارسال شود. درصورتیکه یکی از این پارامترها ارسال نشده باشد یا برابر با رشتهی خالی باشد، پاسخ باید بهصورت زیر باشد:
400
در غیر این صورت، بلاگ باید ثبت شود و پاسخ بهصورت زیر باشد:
201
این endpoint نیازمند authentication است. در ریکوئست ارسالی مقدار هدر Authorization
باید برابر با توکن کاربر باشد (توکن همواره همراه با Bearer
ارسال میشود.).
پارامتر title
و content
باید به این endpoint ارسال شود. درصورتیکه یکی از این پارامترها ارسال نشده باشد یا برابر با رشتهی خالی باشد، پاسخ باید بهصورت زیر باشد:
کد وضعیت: 400
بدنه:
درصورتیکه pk
موجود در URL در دیتابیس وجود نداشته باشد، پاسخ باید بهصورت زیر باشد:
کد وضعیت: 404
بدنه: {}
درصورتیکه کاربر ارسالکنندهی ریکوئست برابر با نویسندهی بلاگ نباشد، پاسخ باید بهصورت زیر باشد:
403
{}
در غیر این صورت، بلاگ باید آپدیت شود و پاسخ بهصورت زیر باشد:
200
این endpoint نیازمند authentication است. در ریکوئست ارسالی مقدار هدر Authorization
باید برابر با توکن کاربر باشد (توکن همواره همراه با Bearer
ارسال میشود.).
پارامتری به این endpoint ارسال نمیشود. در صورتی که pk
موجود در URL در دیتابیس وجود نداشته باشد، پاسخ باید بهصورت زیر باشد:
404
{}
در صورتی که کاربر ارسالکنندهی ریکوئست برابر با نویسنده بلاگ نباشد، پاسخ باید بهصورت زیر باشد:
403
{}
در غیر این صورت، بلاگ باید حذف شود و پاسخ بهصورت زیر باشد:
204
{}
این endpoint نیازمند authentication نیست.
نیازی به ارسال هیچ پارامتری به این endpoint نیست. در همهی حالات، پاسخ باید برابر با مقادیر زیر باشد:
درصورتیکه pk
موجود در URL در دیتابیس وجود نداشته باشد، پاسخ باید بهصورت زیر باشد:
404
{}
در غیر اینصورت، بلاگ باید ثبت شود و پاسخ بهصورت زیر باشد:
200
view
ی بلاگ، یک واحد اضافه کنید و سپس بلاگ را برگردانید. یعنی بازدید فعلی کاربر در میزان بازدیدهای بلاگ برگرداندهشده باید محاسبه شده باشد.نکتهی ریت لیمیت: در اینجا نیاز به پیادهسازی سازوکاری برای ریت لیمیت داریم. میخواهیم هر device_id
و ip
بتواند تنها 10 بار هر بلاگ را ببیند تا میزان ویوهای هر بلاگ، شهودی واقعی از میزان دیدهشدن بلاگ بدهد. تا 10 ریکوئست برای گرفتن یک بلاگ از یک device_id
و ip
را بدون مشکل باز گردانید و مقدار ویوی بلاگ را هم اضافه کنید. به محض عبور از 10 نیاز است که پاسخ برابر زیر باشد و به مقدار ویوی بلاگ هیچ عددی اضافه نشود.
429
{}
این endpoint نیازمند authentication است. در ریکوئست ارسالی مقدار هدر Authorization
باید برابر با توکن کاربر باشد (توکن همواره همراه با Bearer
ارسال میشود.).
پارامتری به این endpoint ارسال نمیشود. درصورتیکه pk
موجود در URL در دیتابیس وجود نداشته باشد، پاسخ باید بهصورت زیر باشد:
404
{}
درصورتیکه توکن Authorization
وجود نداشت و در اصل یوزر لاگین نبود، پاسخ باید بهصورت زیر باشد:
401
{}
در غیر این صورت، باید یک عدد به لایکهای بلاگ اضافه شود و پاسخ بهصورت زیر باشد:
200
این endpoint نیازمند authentication است. در ریکوئست ارسالی مقدار هدر Authorization
باید برابر با توکن کاربر باشد (توکن همواره همراه با Bearer
ارسال میشود.).
درصورتیکه توکن Authorization
وجود نداشت و در اصل یوزر لاگین نبود، پاسخ باید بهصورت زیر باشد:
401
{}
در غیر این صورت، باید مجموع تمام view
و like
های تمام بلاگهای نویسنده را محاسبه کند و پاسخ بهصورت زیر باشد:
200
امتیاز ویژه: در این مسئله داکر فایل و داکر کامپوز در اختیار شماست و نحوهی پیادهسازی کاملاً بر عهدهی خودتان است. اگر دیتابیس مورداستفادهتان را ماندگار و یا persist
کنید، امتیاز بیشتری از مسئله دریافت میکنید.
شما تنها مجاز به استفاده از ایمیجهای موجود در این لینک در داکر فایل و داکر کامپوز خود هستید.
برای حل این سؤال میتوانید از هر زبان و هر تکنولوژیای که میخواهید استفاده کنید. بهصورتیکه در یک پوشه به نام medium
کد برنامه را بنویسید. توجه کنید که حتماً باید Dockerfile
مربوط به پروژهی خود را برای ما ارسال کنید.
docker-compose.yml
تحویلی شما را که در خارج از فولدر medium
قرار دارد، با دستور docker-compose up --build
اجرا میکند.docker-compose.yml
دلخواه هستید.docker-compose.yml
حتما باید برابر با medium
باشد.80
آدرس localhost
قابل دسترسی باشد.0.0.0.0:80
اجرا کنید.3
باشد.شما میتوانید تمامی محتوای موجود در پوشهی medium
را تغییر دهید و هر فایلی که میخواهید اضافه یا کم کنید.
توجه کنید که نام فایل کد شما برای سیستم داوری اهمیتی ندارد و این خود شما هستید که در داکر فایل و داکر کامپوزتان از نام آن برای اجرای پروژه استفاده میکنید.
در نهایت پوشه medium
را به همراه docker-compose.yml
ZIP کرده و ارسال کنید. توجه کنید که پس از extract کردن فایل ZIP شما، باید فایل docker-compose.yml
پوشهی medium
را ببینیم که درون آن Dockerfile
وجود دارد.