مدیریت دانشجویان


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

شما باید این فایل را بخوانید و آن را به شکل زیر به یک لغت‌نامه (dictionary) از نوع JSON تبدیل کنید.

  • کلید هر عنصر این فایل، شماره دانشجویی کاربر شده و مقدار شماره دانشجویی (فیلد id) از داخل عناصر حذف شود.
  • سن دانشجو از روی تاریخ تولد استخراج شود و در کلید age ذخیره شود. دقت کنید که سن دانشجو تا روز برگزاری مسابقه (یعنی 4 اکتبر 2019) محاسبه شود.
  • حرف اول تمامی کلمات در فیلد name بزرگ و باقی حرف‌ها کوچک شوند.
  • در صورتی که یک شماره دانشجویی چند بار در فایل JSON اولیه تکرار شده بود، شما باید اولین تکرار آن شماره را در نظر بگیرید و دیگر تکرارها را حذف کنید.

لغت‌نامه جدید را در قالب JSON در فایل جدیدی با نام ‍students_fixed.json ذخیره کنید.

مثال🔗

مثلا برای فایلی با محتوای زیر:

[{"id":9830011,"bdate":"1994\/9\/24","name":"sardar azmoun"},{"id":9864656,"bdate":"1992\/5\/14","name":"elon MUSK"}]
JSON

فایل جدیدی با خروجی زیر باید تولید شود:

{"9830011":{"bdate":"1994\/9\/24","name":"Sardar Azmoun","age":"25"},"9864656":{"bdate":"1992\/5\/14","name":"Elon Musk","age":"27"}}
JSON

آنچه باید آپلود کنید🔗

فایل پاسخ خود را با نام fixer.php ذخیره کرده و به صورت فایل ZIP آپلود کنید.

عبارات منظم


در این سوال از شما خواسته شده تا اطلاعات مفید را از متن استخراج کنید و یا تغییراتی بر روی آن اعمال نمایید. به این منظور شما باید سه تابع با مشخصات زیر بنویسید که هر کدام یک ورودی متنی دارد و پاسخ درخواستی را برمی‌گرداند:

  1. تابع findPhoneNumbers: این تابع شماره تلفن‌های همراه موجود در متن را تشخیص داده و در قالب یک آرایه برمی‌گرداند. شماره‌های همراه دو حالت دارد:

    • با ‍‍09 شروع شده و دارای ۱۱ رقم است.
    • با +9891 شروع شده و دارای ۱۳ کاراکتر است.

مثالی از ورودی و خروجی این تابع:

"In shomareye mane: 09101007567 vali behtare +989101007567 ro save koni. In 9111231234 va0914513 kar nemikonan."
PHP
 ["09101007567","+989101007567"]
PHP
  1. تابع findHashtags: تمامی کلماتی که با علامت #‍ شروع می‌شوند و تنها شامل اعداد و حروف انگلیسی است را تشخیص داده و در قالب یک آرایه از هشتگ‌ها برمی‌گرداند. این هشتگ‌ها باید شامل حداقل دو حرف به غیر از # باشند.

مثالی از ورودی و خروجی این تابع:

"Salam #goodMOrning khoobi#to #4yourlove #bi-man"
PHP
 ["#goodMOrning","#4yourlove"]
PHP
  1. تابع boldEmails:‍ این تابع تمامی ایمیل‌های موجود در متن را درشت‌دانه (بولد) می‌کند. این تابع تنها ایمیل‌هایی که منطبق بر فرمت username@domain.tld هستند را پشتیبانی می‌کند که:

    • نام کاربری تنها می‌تواند از کاراکتر انگلیسی، عدد، آندرلاین و نقطه تشکیل شود.
    • دامنه تنها می‌تواند از کاراکتر انگلیسی و یا عدد تشکیل شود.
    • tld یک کلمه سه حرفی از کاراکترهای انگلیسی است.
    • کاراکترهای انگلیسی می‌تواند کوچک یا بزرگ باشد

    مثالی از ورودی و خروجی این تابع: ‍‍

    "Soalatono az info_test@Quera.ir ya info@Quera123.com ya test_#23@alaki.core beporsid"
    PHP
"Soalatono az info_test@Quera.ir ya <b>info@Quera123.com</b> ya test_#23@alaki.core beporsid"
PHP

نکات عمومی🔗

نکته ۱: برای سرعت بخشیدن به حل این مسئله، می‌توانید از عبارات منظم به کمک توابع ‍‍preg_grep و preg_replace و یا موارد مشابه استفاده کنید و برای یادگیری قوانین عبارات منظم می‌توانید از این‌جا یا این‌جا کمک بگیرید.

نکته ۲: تمامی موارد درخواستی (شماره همراه/ایمیل/هشتگ) با فاصله از دیگر کلمات جدا شده‌اند و در غیر این صورت، نباید در نظر گرفته شوند.

نکته ۳: ترتیب اعضا در آرایه خروجی شما مهم نیست.

آنچه باید آپلود کنید🔗

هر سه تابع خود را در یک فایل با نام functions.php قرار دهید و به صورت فایل .zip آپلود کنید.

سیستم واقعه‌نگار!


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

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

اما از آنجایی که امیر هنوز به پی‌اچ‌پی مسلط نیست، از شما برای انجام این کار کمک خواسته است.

پروژه اولیه🔗

پروژه اولیه را از اینجا دانلود کنید. ساختار فایل‌های این پروژه به صورت زیر است.

logger
├── LogException.php
├── Logger.php
└── LoggerInterface.php
Plain text

جزئیات🔗

کلاس‌ها🔗

\Quera\LoggerInterface🔗

این کلاس interfaceای است که کلاس Logger باید آن را پیاده‌سازی کند.

این کلاس از PHP Standards Recommendations برداشته شده‌است.

\Quera\Logger🔗

این کلاس کلاسِ اصلی ما است که دارای توابع زیر است:

  • تابع کانستراکتور : دو ورودی می‌گیرد که اولی آدرسی است که لاگ باید در آن ذخیره شود و دومی گزینه‌های مرتبط با روش ذخیره است.

آدرس می‌تواند لینک یک API یا آدرس کامل یک فایل باشد که از طریق type در گزینه‌ها مشخص می‌شود.

آرایه‌ی گزینه‌ها می‌تواند شامل موارد زیر باشد:

> type: نشان‌دهنده نوع ذخیره لاگ هست که می‌تواند file یا api باشد و در صورتی که هیچ‌کدام از این دو نباشد تابع باید یک خطا از نوع LogException پرتاب کند.

> ‍dateFormat: فرمت مورد نظر برای درج تاریخ در لاگ را نشان می‌دهد و از نوع فرمت استاندارد در پی‌اچ‌پی است.

> logFormat: فرمت مورد نظر برای ذخیره لاگ را نشان می‌دهد. این فرمت می‌تواند دارای متغیرهایی باشد که می‌توانند date, level و message باشند یا از طریق متغیر context در توابع لاگ ارسال شوند. هم‌چنین ممکن است در message نیز مانند logFormat متغیر وجود داشته باشد. date با تاریخ با فرمت مورد نظر در dateFormat جایگزین می‌شود. level با اهمیت لاگ با حروف بزرگ جایگزین می‌شود. ‍‍‍message با پیام ارسالی هنگام فراخوانی توابع لاگ جایگزین می‌شود. متغیر‌ها با علامت {} دورشان مشخص می‌شوند.

> threshold: نشان‌دهنده حداقل اهمیت مورد نیاز لاگ برای ذخیره شدن است. اهمیت لاگ‌ها به ترتیب از زیاد به کم از چپ به راست به‌صورت EMERGENCY, ALERT, CRITICAL, ERROR, WARNING, NOTICE, INFO, DEBUG است. اگر برابر ALL قرار داده شود همه سطوح را ذخیره می‌کند. اگر مقداری متفاوت از ۹ مقدار ذکر شده قرار داده شود، باید یک خطا از نوع LogException پرتاب کند.

> append: در صورت انتخاب شدن نوع file، اگر مقدار این متغیر برابر true باشد، لاگ‌ها را به انتهای فایل مشخص شده اضافه می‌کند و در غیر این صورت از ابتدای فایل شروع به نوشتن لاگ‌ها می‌کند. مقدار append تنها در ابتدا برای اولین بار نوشتن در فایل اهمیت دارد.

در صورتی که هرکدام از متغیر‌ها در آرایه ورودی وجود نداشته باشد، مقدار آن از روی جدول زیر باید تعیین شود.

کلید مقدار پیشفرض در صورت تعیین نشدن
type 'file'
dateFormat 'Y-m-d H'
logFormat '[{date}]-[{level}]-{message}'
threshold 'ALL'
append true
  • توابع موجود در LoggerInterface که شامل emergency, alert, critical, error, warning, notice, info, debug که هر کدام یک لاگ با سطح متفاوت ذخیره می‌کنند، می‌باشد. علاوه بر آن‌ها تابع log نیز مانند آن‌ها وجود دارد با این تفاوت که سطح لاگ را با حروف بزرگ به عنوان ورودی دریافت می‌کند.

    با صدا شدن هرکدام ازین ۹ تابع مرتبط به لاگ، باید لاگ در همان زمان طبق گزینه‌های انتخاب شده در کانستراکتور کلاس، در فایل ذخیره شده یا به فرمت POST به API ارسال شود.

\Quera\LogException🔗

این کلاس خطایی است که در صورت وجود اشتباه در آپشن‌های ورودی سازنده کلاس Logger پرتاب می‌شود.

مثال🔗

یک نمونه از اجرای این کلاس به شکل زیر است:

$options = [
    'dateFormat' => 'Y-m-d H',
    'logFormat' => '[{date}] {level}-{message}',
    'threshold' => 'ERROR',
    'append' => true,
];

$logger =  new Quera\Logger("~/debug.log", $options);

$logger->critical('oh oh');
$logger->emergency('system is down');
$logger->notice('change variable name');
$logger->log('ERROR', 'error in line 2');
$logger->error('error in line {variable1}', ['variable1' => '6']);
/* file ~/debug.log:
[2019-10-03 10] CRITICAL-oh oh
[2019-10-03 10] EMERGENCY-system is down
[2019-10-03 10] ERROR-error in line 2
[2019-10-03 10] ERROR-error in line 6
*/
PHP

نکات🔗

  • پروژه اولیه دارای ۳ فایل است که شما تنها می‌توانید در فایل Logger.php تغییرات ایجاد کنید.

  • کلاس Logger لزوما باید LoggerInterface را پیاده‌سازی کند.

  • ‍‍TimeZone را Asia/Tehran قرار دهید.

  • در هنگام ارسال به API پیام باید با عنوان message ارسال شود، به‌ شکلی که با استفاده از $_POST['message'] قابل دسترسی باشد و برای مثال با فرمت اولیه، اگر به شکل

    $logger->emergency('something went wrong...')
    PHP

    فراخوانی شده باشد محتوای $_POST['message'] به شکل

    [2019-10-02 21]-[EMERGENCY]-something went wrong...
    Plain text

    دریافت می‌شود.

بارگذاری🔗

در انتها فایل های زیر را به صورت یک فایل zip آپلود نمایید. نام فایل zip اهمیتی ندارد.

[your-zip-file-name].zip
├── LogException.php
├── Logger.php
└── LoggerInterface.php
Plain text

فروشگاه زنجیره‌ای


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

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

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

ساختار پروژه🔗

ساختار اولیه نرم افزار با استفاده از مدل MVC پیاده سازی شده است و به صورت زیر می باشد:

  • دایرکتوری Controllers: کلاس‌های کنترلر داخل این دایرکتوری قرار گرفته اند. تمامی این کلاس‌ها تحت فضای نام (namespace) Controllers قرار دارند. توجه کنید که شما مجاز به تغییر هیچ کدام از کلاس‌های کنترلر نیستید.
  • دایرکتوری Models: کلاس‌های مدل که مسئول ارتباط با پایگاه داده هستند، داخل این دایرکتوری قرار گرفته اند. تمامی این کلاس‌ها تحت فضای نام (namespace) Models قرار دارند.
  • دایرکتوری Views: فایل‌های نمایش برنامه در این دایرکتوری قرار می گیرند.
  • فایل index.php: نقطه ورودی و مدیریت کلیه درخواست‌ها در سیستم.
  • فایل helpers.php: این فایل مجموعه‌ای از توابع کمکی می باشد.
  • فایل autoload: کلیه توابع مربوط به بارگذاری خودکار فایل‌های php مورد نیاز، در این فایل قرار می گیرند.

آدرس دهی🔗

کلیه درخواست‌ها به فایل index.php ارجاع می شوند. سپس با استفاده از آدرس URL، کنترلر متناسب برای مدیریت درخواست فراخوانی میشود. کنترلر و متد درخواست شده با استفاده از متغیرهای زیر و به صورت Query String در آدرس صفحه قرار میگیرند.

  • controller : نام کنترلر موجود در دایرکتوری Controllers به صورت lowercase در این متغیر قرار می گیرد
  • method: نام متد فراخوانی شده در این متغیر قرار می گیرد.
نمونه :🔗

برای فراخوانی متد index از کنترلر Products آدرس دهی باید به صورت زیر باشد: http://test.dev/index.php?controller=products&method=index

** test.dev یک دامنه فرضی می باشد.

پایگاه داده🔗

برای ذخیره سازی اطلاعات می خواهیم از پایگاه داده Sqlite3 استفاده نماییم. برای این منظور نیاز به دو جدول با ساختار زیر داریم.

1. جدول محصولات (products)🔗
ملاحضات تعریف نوع اسم ستون
PRIMARY KEY شناسه‌ی محصول integer id‍
NOT NULL UNIQUE عنوان محصول text title
NOT NULL قیمت محصول integer price
NOT NULL حداکثر تعداد قابل خریداری برای هر شخص integer maximum_count
2. جدول سبد خرید (carts)🔗
ملاحضات تعریف نوع اسم ستون
PRIMARY KEY شناسه‌ integer id‍
NOT NULL شناسه سبد خرید کاربر text cart_identifier
NOT NULL شناسه محصول خریداری شذه integer product_id
NOT NULL تعداد محصول خریداری شده integer product_count

شما باید فایل دیتابیس را به نام db.sqlite در دایرکتوری اصلی، در کنار فایل index.php ایجاد نمایید.

پروژه اولیه🔗

پروژه اولیه را می‌توانید از اینجا دانلود کنید.

پیاده سازی🔗

3. پیاده سازی توابع کمکی🔗

در فایل helpers.php نیار به پیاده سازی چند تابع داریم.

  • resolve_request_parameter($name, $default = null)

این تابع را به گونه‌ای پیاده سازی نمایید که بتواند مقدار $name را در متغیر $_GET یا $_POST جستحو نماید و مقدار آنرا برگرداند. در صورتی که این متغیر یافت نشد، باید مقدار $default بازگردانده شود.

  • redirect($controller = '', $method = '')

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

  • set_alert($alert)

این تابع را به گونه‌ای پیاده سازی نمایید که رشته دریافت شده را به گونه‌ای در سیستم ذخیره نماید، که این متغیر تنها یک بار بعد از redirect به کاربر نمایش داده شود. برای این کار می توانید از Session کمک بگیرید.

  • get_alert()

این تابع را به گونه ای پیاده سازی نمایید که پیام ثبت شده توسط set_alert را برای نمایش در فایل‌های view بازگرداند. توجه کنید که هر پیام تنها یکبار قابلیت نمایش دارد و در صورت refresh کردن صفحه، هیچ پیامی نباید نمایش داده شود. همجنین در صورتی که هیچ پیامی تنظیم نشده بود، باید مقدار null برگشت داده شود.

  • get_cart_identifier()

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

1. پیاده سازی ساختار autoload🔗

در هیچ کدام از کلاس‌ها نباید از روش‌های بارگزاری مستقیم فایل (شامل require, include, require_once, include_once) استفاده نمود. شما باید با استفاده از متدهای پیش بینی شده در php برنامه را به گونه‌ای تغییر دهید که در صورت نیاز به هر کلاس، برنامه به طور خودکار فایل مربوط به آن کلاس را بارگذاری نماید. توجه کنید که نام namespace ها برابر نام دایرکتوری و نام class ها برابر نام فایل می باشد. توابع پیاده سازی شده را در فایل autoload.php قرار دهید.

2. پیاده سازی ساختار مدل‌ها🔗

همه کلاس‌های مدل‌ها از کلاس DatabaseModel ارث بری می کنند. شما باید منطق این کلاس را به گونه‌ای پیاده سازی نمایید که عملیات‌های زیر را به درستی انجام دهد.

  • getConnection()

این متد باید یک شی از توع SQLite3 که به دیتابیس متصل شده است را برگرداند.

  • $attributes

با استفاده از توابع پیش بینی شده در php این کلاس را به گونه‌ای توسعه دهید، که متغیرهای جدید منتسب شده را در آرایه $attributes قرار دهد. همچنین در صورت دسترسی به متغیرهای ثبت نشده در کلاس، سعی کند نام متغیر را از آرایه $attributes بخواند.

نمونه:

    $product = new \Models\Product();

    $product->title = "Pencil";

    $product->price = 10000
PHP

بعد ار اجرای این کد متغیر $attributes باید به صورت آرایه ای شامل عناصر زیر باشد:

[
    "title": "Pencil",
    "price": 10000",
]
PHP

همجنین در صورت فراخوانی متغیرهای دیگر، آرایه $attributes باید مورد جستجو قرار گیرد.

    echo $product->title;

    echo $product->price;
PHP

خروجی این کد باید به صورتزیر باشد:

"Pencil"
10000
Plain text

ضمنا توجه کنید که اگر در هنگام نمونه سازی از کلاس Model ها، لیستی از مقادیر را به تابع سازنده ارسال کنیم، این مقادیر در آرایه $attributes قرار می گیرند.

3. نصب سیستم🔗

برای نصب سیستم باید به آدرس index.php?controller=install&method=index مراجعه نمایید.

نصب سیستم شامل پروسه ایجاد جداول پایگاه داده می باشد. تابع buildSchema در هر کلاس مدل مسئولیت ایجاد جدول مربوط به خود را دارد. تابع buildSchema موجود در کلاس \Models\Product و \Models\Cart را به گونه‌ای تغییر دهید که بعد از فراخوانی جداول مورد نیاز را ایجاد کند.

4. نمایش لیست محصولات🔗

برای نمایش لیست محصولات باید به آدرس index.php?controller=products&method=index مراجعه نمایید.

برای نمایش صحیح محصولات، متد all از کلاس Models\Product را به گونه‌ای تغییر دهید که یک آرایه شامل لیستی از instance های Models\Product را با مقادیر درست بازگرداند. هر کدام از instance های محصولات باید شامل مقادیر زیر باشد:

    $product->id
    $product->title
    $product->price
    $product->maximum_count
PHP

محصولات باید به ترتیب درج شدن، روی لیست نمایش داده شود. توجه کنید که شما مجاز به تغییر کنترلر Controllers\Products نمی باشید. تمامی تغییرات باید روی مدل Models\Product اعمال گردد.

5. افزودن محصول جدید🔗

برای نمایش فرم محصول جدید باید به آدرس index.php?controller=products&method=form مراجعه نمایید.

متد create از مدل Models\Product را به گونه‌ای تغییر دهید، که با دریافت پارامترهای نوشته شده، اطلاعات محصول جدید را در دیتابیس ذخیره نماید. سپس یک نمونه از Models\Product را با کلیه اطلاعات محصول ثبت شده، شامل id, title, price, maximum_count باز گرداند.

6. دریافت اطلاعات محصول🔗

متد find از کلاس Models\Product را به گونه ای پیاده سازی نمایید، که با دریافت id محصول، کلیه اطلاعات محصول را از دیتابیس گرفته و به صورت یک شی Models\Product بازگرداند. در صورتی که هیچ محصولی با id ذکر شده یافت نشد، سیستم باید یک Exception با پیغام Model Not Found پرتاب نماید.

7. خرید محصول🔗

در لیست محصولات با کلیک بر روی لینک Buy به آدرس index.php?controller=carts&method=add هدایت می شوید. شما باید تابع purchase از مدل Models\Cart را به گونه‌ای پیاده سازی نمایید که با دریافت شناسه سبد خرید کاربر و یک شی Models\Product به عنوان ورودی اقدامات زیر را انجام دهد:

  • در صورت که کاربر قبلا از این محصول در سبد خود اضافه نکرده بود، این محصول را به سبد خرید کاربر اضافه نماید.
  • در صورتی که کاربر قبلا این محصول را به سبد خرید خود اضافه کرده بود، باید مقدار product_count آن یک واحد افزایش یابد.
  • در صورتی که کاربر قبلا حداکثر مقدار قابل سفارش از این محصول را به سبد خود اضافه کرده بود، باید یک Exception با پیام Maximum Count Reached پرتاب شود.

8. نمایش محصولات موجود در سبد خرید🔗

برای نمایش لیست محصولات سبد خرید کاربر باید به آدرس index.php?controller=carts&method=index مراجعه نمایید.

برای نمایش لیست سبد خرید باید تابع getProducts از کلاس Models\Cart را به گونه ای تغییر دهید که یک آرایه شامل نمونه‌هایی از کلاس Models\Cart را بازگرداند. هر instance از کلاس Models\Cart باید شامل اطلاعات زیر باشد.

    $cart->id;              // id ثبت شده در جدول carts
    $cart->title;           // عنوان محصول خریداری شده
    $cart->price;           // قیمت هر عدد از محصول خریداری شده ( قیمت FEE)
    $cart->product_id;      // id محصول انتخاب شده در حدول products
    $cart->product_count;   // تعداد سفارش از این محصول
    $cart->total_price;     // حاصل ضرب قیمت محصول در تعداد سفارش محصول
PHP

همچنین شما باید متد calculateTotalPrice را به گونه ای پیاده سازی نمایید که با دریافت لیست تولید شده توسط تابع getProducts، بتواند مجموع کل قیمت سفارش را محاسبه نماید.

9. حذف یک محصول از سبد خرید🔗

در لیست سبد خرید با کلیک روی لینک Add به متد purchase که قبلا پیاده سازی نمودیم، هدایت می شویم.

در صورت کلیک روی لینک Remove به آدرس index.php?controller=carts&method=remove هدایت می شویم. در این مسیر، محصول انتخاب شده باید از سبد خرید به طور کلی حذف شود. برای این کار باید متد remove از کلاس Models\Cart را به گونه ای تغییر دهید، که با دریافت شناسه سبد خرید کاربر و یک instance از Models\Product، اقدامات زیر را انجام دهد:

  • در صورتی که محصول در سبد خرید کاربر وجود داشت، از سبد خرید حذف می شود.
  • در صورتی که این محصول در سبد خرید کاربر وجود نداشت، یک Exception با پیام Product Not Available باید پرتاب شود.

ارسال نتیجه🔗

در نهایت فایل‌ها و فولدر‌های زیر را بدون تغییر ساختار فولدر بندی، در یک فایل zip ارسال نمایید.

/Models/Cart.php
/Models/Product.php
/Models/DatabaseModel.php
/helpers.php
/autoload.php
Plain text

دانیال همراه


سامانه دانیال همراه🔗

یکی از شرکت های معتبر واردات قعطات کامپیوتری (به نام دانیال همراه) هر ماه قطعاتی را از کشورهای مختلف وارد می کند. این شرکت اخیرا با مشکلات متعددی برای امور گارانتی خود مواجه شده است. روال گارانتی به این صورت است که الزاما بایستی شماره سریال قطعه مورد نظر توسط خریدار نهایی به شرکت اعلام شود. به همین دلیل شرکت برای هر دستگاه یک کارت گارانتی چاپ کرده که بر روی کارت شماره سریال قطعه و همچنین کد فعالسازی گارانتی چاپ شده است. کد فعالسازی به صورت مخفی و تحت یک scratch code بر روی کارت چاپ می شود.

حال می خواهیم سیستمی با مشخصات زیر برای ارائه کدهای گارانتی به مشتریان شرکت پیاده سازی کنیم.

پروژه اولیه🔗

فایل های پروژه اولیه را می توانید از اینجا دانلود کنید. این پروژه بر اساس کتابخانه لاراول نسخه 5.8.* پیاده سازی خواهد شد.

فایل هایی که اضافه بر ساختار معمول پروژه های لاراول در اختیار شما قرار شده است عبارتند از :

  • فایل input.xlsx که در مسیر storage/app/input.xlsx قرار داده شده است. این فایل از طرف شرکت به ما داده می شود و شامل دو ستون است. ستون اول یا A کد یکتای شناسایی محصولات (شبیه به شماره سریال) بوده و ستون دوم کد فعالسازی است که شرکت به صورت تصادفی برای هر قطعه مشخص کرده.

  • فایل CValidator.php که در مسیر app/CValidator.php قرار داده شده است و شامل تابع اعبتارسنجی کد ملی است که برای قسمت اعتبارسنجی می توانید از آن استفاده کنید.

  • فایل های مورد نیاز برای قسمت Frontend که در پوشه های resource/views/home و public/css قرار داده اند تا نیازی به توسعه css/html از سمت شما به حداقل ممکن برسد.

لیست نیازمندی ها🔗

  • با توجه با اینکه مدیریت شرکت نسبت به امنیت سامانه بسیار حساس است، مخالفت بسیار زیادی با این پروژه داشته است. لذا به ایشان اطمینان دادیم که امنیت سامانه به نحوی تامین شود که اگر حتی کل فایل ها و پایگاه داده برنامه مورد حمله واقع شد اطلاعات کد های فعالسازی دچار مشکل و دستبرد نشود. به همین دلیل امکان استفاده مستقیم از فایل اکسل ورودی را نداریم. بایستی یک دستور Artisan به نام GenerateFile ایجاد کنید تا با فراخوانی این دستور یک فایل csv به این صورت ایجاد شود که هر سطر آن معادل یک سطر در فایل اکسل بوده با این تفاوت که فیلد شماره سریال ها (فیلد اول) به صورت hash شده با الگوریتم sha1 ذخیره شود و فیلد دوم با استفاده از کلاس Crypto لاراول رمز نگاری شود. در اینصورت حتی اگر کل اطلاعات در دسترس نفر دیگری قرار بگیرد بدون داشتن شماره سریال ها به صورت palin text نمی تواند از کدهای گارانتی استفاده کند. برای انجام این قسمت در نظر داشته باشید که فایل csv با نام data.csv در آدرس storage/app/data.csv باید ساخته شود و کاراکتر delimiter حتما بایستی , باشد اما خط ابتدای فایل که نام field ها در آن نوشته می شود مورد داوری قرار نمیگیرد و مختارید که از هر نامی استفاده کنید ولی وجود آن الزامی است.

  • لیست route های مورد نیاز در فایل routes/web.php از قبل نوشته شده است. برنامه به صورت یک فرم ۳ مرحله ای بوده و در هر مرحله اطلاعات مورد نیاز دریافت و اعتبارسنجی (validate) می شوند.

    • در مرحله اول فیلدهای نام و نام خانوداگی صرفا خالی یا پر بودنشان ملاک بررسی است. هیچ شرط اضافه ای نخواهند داشت.

    • فیلد کد ملی علاوه بر شرط پر بودن باید با توجه به تابع موجود در فایل CValidator مورد بررسی قرار گرفته تا از اعتبار اولیه آن مطمئن شویم.

    • منظور از فیلد کد گارانتی همان فیلد serial_number در فایل اکسل است که علاوه بر شرط پر بودن باید در لیست ارائه شده نیز موجود باشد. یعنی مقدار وارد شده توسط کاربر را بررسی خواهیم کرد که آیا در محتویات ستون اول فایل اکسل وجود دارد یا نه؟. ضمنا این فیلد بایستی از نظر تعداد کاراکتر ها (که ۲ کاراکتر عددی می باشد) نیز مورد بررسی قرار بگیرد

    • در صورتیکه کلیه اطلاعات به درستی وارد شد، کاربر را به صفحه دوم منتقل میکنیم و قبل از آن دو کلید در session ست می کنیم. اول کلید gid که همان کد گارانتی است که کاربر به درستی وارد کرده و دوم کلید code که محتوی کد موقتی است که برای اعتبار سنجی کاربر مورد استفاده قرار خواهد گرفت.

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

    • با ارسال فرم در مرحله دوم اولا بررسی خواهیم کرد که کلید های session که در مرحله اول ست شده بودند همچنان وجود داشته و مقادیر آنها معتبر باشند (در صورت عدم وجود کلید ها بایستی کاربر به مرحله قبل منتقل شود) و دوما مقدار code که کاربر وارد میکند با کدی که در مرحله ۱ تولید شده است یکسان و همخوان باشد. ضمنا فیلد code بایستی از نظر تعداد کاراکتر ها (که ۶ کاراکتر عددی می باشد) نیز مورد بررسی قرار بگیرد

    • در صورتیکه کد موقت به درستی وارد شود، کاربر را به مرحله سوم منتقل میکنیم و کد فعالسازی متناظر با کد گارانتی وارد شده را رمزگشایی کرده و به او نمایش میدهیم.

  • لطفا نکات زیر را برای داوری صحیح پاسخ هایتان در نظر داشته باشید :

    -ملاک بررسی صحت اعتبارسنجی های انجام شده کلید errors در session می باشد که به صورت عادی توسط لاراول ست می شود. به بیان دیگر حتما سعی کنید از توابع و کلاس های موجود در لاراول برای اعتبارسنجی و تولید خطاهای احتمالی استفاده کنید تا کمترین میزان مغایرت با داوری را داشته باشید. به این منظور می توانید از قسمت Validation کمک بگیرید.

    -پیغام های تولید شده در اعتبار سنجی ها کاملا باید مطابق لیست زیر باشد (واضح است که حتی ۱ کاراکتر اختلاف باعث رد شدن جواب خواهد شد) :

    
      پر کردن فیلد نام اجباری می باشد
    
      پر کردن فیلد نام خانوادگی اجباری می باشد
    
      پر کردن فیلد کد ملی اجباری می باشد
    
      کد ملی وارد شده صحیح نمی باشد
    
      پر کردن فیلد کد گارانتی اجباری می باشد
    
      کد گارانتی وارد شده معتبر نمی باشد
    
      تعداد رقم های وارد شده برای کد گارانتی صحیح نمی باشد
    
      پر کردن فیلد کد موقت اجباری می باشد
    
      تعداد رقم های وارد شده برای کد موقت صحیح نمی باشد
    
      کد موقت وارد شده صحیح نمی باشد
    
      کد فعالسازی شما عبارت است از : 13
    
    Plain text
  • در نظر داشته باشید که در طول برنامه پس از تولید فایل data.csv فایل ورودی اکسل اولیه حذف خواهد شد و دیگر در دسترس نخواهد بود. لذا در ادامه بایستی همه چیز با استفاده از اطلاعات فایل تولید شده بررسی و ارائه شود.

  • برای استخراج اطلاعات از فایل اکسل می توانید از کتابخانه های آماده استفاده کنید و فایل composer.json را همراه پاسخ خود آپلود کنید.

  • در صفحات مختلف، نسبت به مرحله ای که فعال می باشد، بایستی وضعیت نمایش داده شده در بالای فرم (که مراحل را به صورت فعال و غیر فعال نمایش می دهد) صحیح باشد. مثلا در صفحه ای که آدرس آن /step2 است باید مراحل ۱ و ۲ هردو فعال باشند (کلاس active به عنصر li داده شود).

آنچه باید آپلود کنید🔗

پوشه های زیر را در یک فایل فشرده با فرمت zip آپلود کنید :


app

config

resources

routes

composer.json
Plain text

تصحیح🔗

  • گویا فایل input.xlsx که در پروژه اولیه قرار داده شده با نرم افزار اکسل مشکل دارد و باز نمی‌شود. اول این که فایل از نظر محتوایی سالمه و با کدهای php میشه محتواش رو خوند و دوم اینکه می‌تونید همون فایل رو با google sheet باز کنید یا اینکه فایل جدید رو از این آدرس دانلود کنید و جایگزین کنید.
  • در مرحله دوم در صورتیکه همه چیز صحیح باشد، بایستی کد فعالسازی به صورت رمزگشایی شده در یک متغیر session با کلید activation_code قرار بگیرد و کاربر به مرحله سوم منتقل شده و کد فعالسازی به کاربر نشان داده شود.