سلام کدکاپ ۶!


قطعاً با جمله‌ی معروف «سلام دنیا!» آشنایی دارید:

<?php

echo 'Hello, World!';
PHP

کدکاپی‌ها قصد دارند برای دست‌گرمی به کدکاپ ۶ سلام دهند، اما نمی‌خواهند این کار را به سادگی کد بالا انجام دهند. آن‌ها می‌خواهند تابعی برای این کار پیاده‌سازی کنند که توضیحات آن در ادامه آمده است.

جزئیات پروژه🔗

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

پروژه‌ی اولیه شامل فایلی با نام sayHello.php است که تابعی با نام sayHello در آن تعریف شده. امضای این تابع به‌صورت زیر است:

function sayHello(array $words, int $reverseIndex): void
{
    // TODO: Implement
}
PHP

این تابع را طوری پیاده‌سازی کنید که رشته‌ی موجود در اندیس reverseIndex آرایه‌ی words را معکوس کند، سپس رشته‌های موجود در آرایه‌ی words را با یک space () به یکدیگر بچسباند و رشته‌ی حاصل را چاپ (echo) کند. کاراکتر \n نیز در انتها باید چاپ شود تا با هر فراخوانی sayHello، خروجی در یک خط مجزا چاپ شود.

تضمین می‌شود که اندیس reverseIndex در آرایه‌ی words تعریف شده است.

مثال🔗

پس از پیاده‌سازی تابع sayHello، با اجرای کد زیر:

<?php

function sayHello(array $words, int $reverseIndex): void
{
    // TODO: Implement
}

sayHello(['Hello', 'puCedoC', '6!'], 1);
sayHello(['malaS', 'CodeCup', '6!'], 0);
PHP

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

Hello CodeCup 6!
Salam CodeCup 6!
Plain text

توجه: کاراکتر space () اضافه نباید در خروجی موجود باشد.

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

یک فایل PHP که تابع sayHello در آن پیاده‌سازی شده است آپلود کنید.

تست سئو


سئو، سئو و سئو!

سئو جدیداً به یکی از دغدغه‌های جدی علی تبدیل شده است. او دائماً صفحات وب‌سایت خود را چک می‌کند تا اشتباهی از او سر نزده باشد که باعث افت رنک وبسایتش شود. به همین دلیل، علی به‌صورت جدی در تلاش است تا برنامه‌ای بنویسد تا صفحات سایتش را از لحاظ سئو بررسی کند.

او از شما برای نوشتن چنین برنامه‌ای کمک خواسته است.

جزئیات پروژه🔗

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

پروژه‌ی اولیه شامل فایلی با نام seoScore.php است که تابعی با نام seoScore در آن تعریف شده. امضای این تابع به‌صورت زیر است:

function seoScore(string $html): int
{
    // TODO: Implement
}
PHP

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

برای بررسی صفحه و اختصاص امتیاز به آن باید به نکات زیر توجه کنید:

  • اگر صفحه دارای تگ title بود و تعداد کاراکتر‌های محتوای این تگ کوچک‌تر یا مساوی ۶۰ بود، ۱۰ امتیاز و اگر بیشتر از ۶۰ کاراکتر بود، ۷ امتیاز اضافه شود. تضمین می‌شود که این تگ در صورت وجود، بدون attribute و به شکل زیر خواهد بود:
    <title>Page Title</title>
    HTML
  • اگر صفحه دارای تگ meta با نام description بود و تعداد کاراکتر‌های محتوای ویژگی content این تگ کوچک‌تر یا مساوی ۱۶۰ بود، ۱۰ امتیاز و اگر بیشتر از ۱۶۰ کاراکتر بود، ۷ امتیاز اضافه شود. تضمین می‌شود که این تگ در صورت وجود، با این ترتیب از attribute ها خواهد بود:
    <meta name="description" content="description-content">
    HTML
  • اگر صفحه دارای تگ meta با نام viewport بود، ۱۰ امتیاز اضافه شود. تضمین می‌شود که این تگ در صورت وجود، با این ترتیب از attribute ها خواهد بود:
    <meta name="viewport" content="viewport-content">
    HTML
  • اگر صفحه دارای تگ meta با نام robots بود، ۱۰ امتیاز اضافه شود. تضمین می‌شود که این تگ در صورت وجود، با این ترتیب از attribute ها خواهد بود:
    <meta name="robots" content="robots-content">
    HTML
  • اگر صفحه دارای تگ meta با ویژگی charset بود، ۱۰ امتیاز اضافه شود. تضمین می‌شود که این تگ در صورت وجود، با این ترتیب از attribute ها خواهد بود:
    <meta charset="charset-value">
    HTML
  • اگر صفحه دارای یک تگ h1 بود، ۱۰ امتیاز و اگر بیشتر از یک تگ h1 بود، ۷ امتیاز اضافه شود. تضمین می‌شود که این تگ در صورت وجود، بدون attribute است.
  • اگر صفحه دارای تگ‌های h2 یا h3 بود، به ازای هر یک از این تگ‌ها ۵ امتیاز اضافه شود (تعداد تگ‌های h2 و h3 اهمیتی ندارد). تضمین می‌شود که این تگ‌ها در صورت وجود، بدون attribute هستند.
  • اگر صفحه دارای تگ‌های معنایی بود، به ازای هر یک از این تگ‌ها ۱۰ امتیاز اضافه شود (تگ‌های معنایی یا semantic tags در این سؤال شامل header، section و footer است؛ تعداد دفعات تکرار آن‌ها اهمیتی ندارد). تضمین می‌شود که این تگ‌ها در صورت وجود، بدون attribute هستند.

نکات🔗

  • ممکن است در ابتدا یا انتهای محتویات تگ‌ها و attribute ها whitespace آمده باشد. برای بررسی طول این متون، باید whitespace ابتدا و انتها را نادیده بگیرید (آن‌ها را trim کنید).
  • ممکن است محتویات تگ‌ها خالی باشد. برای مثال، اگر یک تگ footer بدون محتوا در HTML موجود باشد، باید ۱۰ امتیاز اضافه شود.
  • تضمین می‌شود که نام تگ‌ها و attribute ها با حروف کوچک انگلیسی هستند.
  • تضمین می‌شود که رشته‌ی HTML ورودی از نظر سینتکس معتبر است.
  • در صورت تمایل، می‌توانید توابع و کلاس‌های دیگری نیز در فایل seoScore.php پیاده‌سازی کنید.

مثال🔗

پس از پیاده‌سازی متد seoScore، با اجرای کد زیر:

<?php

function seoScore(string $html): int
{
    // TODO: Implement
}

$html =
    '<!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Quera</title>
        <meta name="description" content="quera-codecup-college-magnet">
        <meta name="robots" content="index, follow">
    </head>
    <body>
    <header>
        <h1>Quera</h1>
    </header>
    <section>
        <h2>Quera</h2>
        <h3>Quera</h3>
        <h3>Quera</h3>
        <h3>Quera</h3>
    </section>
    <footer>
        <h2>Quera</h2>
    </footer>
    </body>
    </html>';

echo seoScore($html);
PHP

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

100
Plain text

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

یک فایل PHP که تابع seoScore در آن پیاده‌سازی شده است آپلود کنید.

لاگچری


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

او قسمت‌هایی از این پروژه را انجام داده، اما در پیاده‌سازی بعضی از قسمت‌ها به مشکل خورده است. شما باید برای قسمت‌هایی از پروژه که او به مشکل خورده است به او کمک کنید.

جزئیات پروژه🔗

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

ساختار فایل‌ها
logtury
├── app
│   └── Controllers
│       └── HomeController.php
├── core
│   ├── Logger.php
│   ├── Router.php
│   ├── View.php
│   └── routes.php
├── public
│   ├── assets
│   │   └── plugins
│   │       └── tailwind
│   │           └── tailwind.min.css
│   └── index.php
├── resources
│   └── views
│       ├── about.php
│       ├── contact.php
│       └── index.php
├── storage
│   └── logs
├── test
│   └── LogturySampleTest.php
├── composer.json
└── composer.lock
Plain text
راه‌اندازی پروژه

برای اجرای پروژه، باید php و composer را از قبل نصب کرده باشید.

  • پروژه‌ی اولیه را دانلود و از حالت فشرده خارج کنید.
  • دستور composer install را در پوشه‌ی اصلی پروژه برای نصب نیازمندی‌ها اجرا کنید.
  • دستور php -S 127.0.0.1:8000 -t public را در پوشه‌ی اصلی پروژه اجرا کنید. پروژه از طریق آدرس http://127.0.0.1:8000 در دسترس خواهد بود.

در اولین گام باید کد‌های این پروژه را مطالعه کرده و با منطق پروژه آشنا شوید. در ادامه، باید تغییراتی که در ادامه ذکر شده است را در پروژه اعمال کنید.

ابتدا باید کلاس Core\Logger را پیاده‌سازی کنید، اگر به این کلاس مراجعه کنید خواهید دید که دارای کانستراکتور و دو متد writeLog و getLog است، پیاده‌سازی هر‌کدام باید به‌صورت زیر باشد:

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

سپس باید روت‌های زیر را به پروژه اضافه کنید:

  • روت / که باید متد index از کلاس HomeController را فراخوانی کند.
  • روت /about-us که باید متد about از کلاس HomeController را فراخوانی کند.
  • روت /contact-us که باید متد contact از کلاس HomeController را فراخوانی کند.

در انتها باید این متد‌ها را در کنترلر HomeController پیاده‌سازی کنید به نحوی که اگر هر روت فراخوانی شد، ابتدا در فایل storage/logs/app.log و در یک خط عبارتی با قالب زیر درج شود:

[CURRENT_DATE_TIME] - [NAME] Page Visited
Plain text

در قالب بالا CURRENT_DATE_TIME به‌معنی تاریخ و ساعت کنونی است که باید با فرمت Y-m-d H:i:s باشد و مقدار NAME هم باید برای روت / برابر با Home، برای روت /about-us برابر با About و برای روت /contact-us برابر با Contact باشد.

سپس ویوی مربوط به هر روت render و برگردانده شود (با استفاده از کلاس View):

  • برای روت / ویوی resources/views/index
  • برای روت /about-us ویوی resources/views/about
  • برای روت /contact-us ویوی resources/views/contact

مثال🔗

فرض کنید کاربری به‌ترتیب روت‌های / سپس /about-us و در انتها /contact-us را می‌بیند. در نهایت، باید مقادیر زیر در فایل storage/logs/app.log ذخیره شده باشند (خروجی متد getLog):

2021-11-19 18:05:06 - Home Page Visited
2021-11-19 18:05:08 - About Page Visited
2021-11-19 18:05:09 - Contact Page Visited
Plain text

با ارسال درخواست به آدرس /، کاربر باید با صفحه‌ی زیر مواجه شود:

صفحه‌ی اصلی

نکات🔗

  • این پروژه از استاندارد PSR-4 برای autoloading کلاس‌ها استفاده می‌کند.
  • شما تنها مجاز به اعمال تغییرات در پوشه‌ی app و فایل‌های core/Logger.php و core/routes.php هستید.

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

پس از اعمال تغییرات، پوشه‌های app و core را زیپ کرده و آپلود کنید.

QCLI


هنگام انجام کارها یا آن ها را با عشق انجام دهید یا هرگز انجام ندهید.

این جمله از گاندی رضا را به این فکر فرو برده است که فکری برای انجام بسیاری از کار‌های تکراری که باید به‌طور متناوب انجام دهد بکند. به‌عنوان مثال او از خط فرمان (command-line) خیلی استفاده می‌کند و همیشه آرزو داشت تا دستوراتی را خودش ایجاد و از آن‌ها استفاده کند.

در این سؤال باید به‌همراه او این آرزو را برآورده کنید.

جزئیات پروژه🔗

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

ساختار فایل‌ها
qcli
├── core
│   ├── Commands
│   └── Command.php
├── stubs
│   └── command.stub
├── test
│   └── QCliSampleTest.php
├── composer.json
├── composer.lock
└── qcli
Plain text
راه‌اندازی پروژه

برای اجرای پروژه، باید php و composer را از قبل نصب کرده باشید.

  • پروژه‌ی اولیه را دانلود و از حالت فشرده خارج کنید.
  • دستور composer install را در پوشه‌ی اصلی پروژه برای نصب نیازمندی‌ها اجرا کنید.

در دایرکتوری اصلی پروژه، فایلی به نام qcli وجود دارد که یک اسکریپت PHP است. از این فایل برای هندل کردن دستورات استفاده می‌شود. این فایل پس از دریافت دستور، پارامتر‌های ورودی را برای اجرا به متد run کلاس QCli\Command ارسال می‌کند.

در ابتدا باید برنامه را طوری پیاده‌سازی کنید که دستور make:command name sign به‌صورت پیش‌فرض در برنامه موجود باشد. name نام کلاس دستور و sign امضای دستور است. وظیفه‌ی این دستور این است که دستورات دلخواه را در دایرکتوری core/Commands ایجاد کند. قالب دستوراتی که ایجاد می‌شوند باید مطابق محتویات فایل stubs/command.stub باشد:

extensionFromNamestubs/command.stub
<?php

namespace QCli\Commands;

class {{ name }}
{
    protected string $signature = '{{ sign }}';

    protected string $description = '{{ name }} description';

    public function handle()
    {
        echo 'Command ' . $this->signature . ' is ready to implement';
    }
}
PHP

فرض کنید دستور زیر در خط فرمان وارد می‌شود:

php qcli make:command CustomCommand custom:command
Shell

با اجرای دستور فوق، باید فایل CustomCommand.php در مسیر core/Commands ساخته شود:

extensionFromNamecore/Commands/CustomCommand.php
<?php

namespace QCli\Commands;

class CustomCommand
{
    protected string $signature = 'custom:command';

    protected string $description = 'CustomCommand description';

    public function handle()
    {
        echo 'Command ' . $this->signature . ' is ready to implement';
    }
}
PHP

هم‌چنین ممکن است کلاس‌هایی به‌صورت دستی (بدون استفاده از دستور پیش‌فرض make:command) در مسیر core/Commands ایجاد شوند. برنامه باید بتواند این دستورات را نیز شناسایی کند. تضمین می‌شود که این کلاس‌ها نیز مطابق محتویات فایل stubs/command.stub هستند.

اگر دستور ایجادشده در خط فرمان وارد شود، باید متد handle از کلاس دستور اجرا شود، یعنی در مثال قبل اگر دستور زیر وارد شود:

php qcli custom:command
Shell

باید عبارت Command custom:command is ready to implement چاپ شود.

نکات🔗

  • تضمین می‌شود که دو دستور با نام کلاس یا امضای یکسان ایجاد نخواهد شد.
  • این پروژه از استاندارد PSR-4 برای autoloading کلاس‌ها استفاده می‌کند.
  • شما تنها مجاز به اعمال تغییرات در دایرکتوری core هستید. می‌توانید فایل‌ها و دایرکتوری‌های جدیدی نیز در این دایرکتوری ایجاد کنید.
  • در صورت نیاز، می‌توانید متدهای دیگری نیز در کلاس QCli\Command پیاده‌سازی کنید.

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

پس از اعمال تغییرات، پوشه‌ی core را زیپ کرده و آپلود کنید.