قطعاً با جملهی معروف «سلام دنیا!» آشنایی دارید:
```php
<?php
echo 'Hello, World!';
```
کدکاپیها قصد دارند برای دستگرمی به کدکاپ ۶ سلام دهند، اما نمیخواهند این کار را به سادگی کد بالا انجام دهند. آنها میخواهند تابعی برای این کار پیادهسازی کنند که توضیحات آن در ادامه آمده است.
## جزئیات پروژه
پروژهی اولیه را از [این لینک](/contest/assignments/35047/download_problem_initial_project/121222/) دانلود کنید.
پروژهی اولیه شامل فایلی با نام `sayHello.php` است که تابعی با نام `sayHello` در آن تعریف شده. امضای این تابع بهصورت زیر است:
```php
function sayHello(array $words, int $reverseIndex): void
{
// TODO: Implement
}
```
این تابع را طوری پیادهسازی کنید که رشتهی موجود در اندیس `reverseIndex` آرایهی `words` را معکوس کند، سپس رشتههای موجود در آرایهی `words` را با یک *space* (` `) به یکدیگر بچسباند و رشتهی حاصل را چاپ (`echo`) کند. کاراکتر `\n` نیز در انتها باید چاپ شود تا با هر فراخوانی `sayHello`، خروجی در یک خط مجزا چاپ شود.
**تضمین میشود** که اندیس `reverseIndex` در آرایهی `words` تعریف شده است.
## مثال
پس از پیادهسازی تابع `sayHello`، با اجرای کد زیر:
```php
<?php
function sayHello(array $words, int $reverseIndex): void
{
// TODO: Implement
}
sayHello(['Hello', 'puCedoC', '6!'], 1);
sayHello(['malaS', 'CodeCup', '6!'], 0);
```
خروجی باید بهصورت زیر باشد:
```
Hello CodeCup 6!
Salam CodeCup 6!
```
**توجه:** کاراکتر *space* (` `) اضافه نباید در خروجی موجود باشد.
## آنچه باید آپلود کنید
یک فایل *PHP* که تابع `sayHello` در آن پیادهسازی شده است آپلود کنید.
سئو، سئو و سئو!
سئو جدیداً به یکی از دغدغههای جدی علی تبدیل شده است. او دائماً صفحات وبسایت خود را چک میکند تا اشتباهی از او سر نزده باشد که باعث افت رنک وبسایتش شود. به همین دلیل، علی بهصورت جدی در تلاش است تا برنامهای بنویسد تا صفحات سایتش را از لحاظ سئو بررسی کند.
او از شما برای نوشتن چنین برنامهای کمک خواسته است.
## جزئیات پروژه
پروژهی اولیه را از [این لینک](/contest/assignments/35047/download_problem_initial_project/121219/) دانلود کنید.
پروژهی اولیه شامل فایلی با نام `seoScore.php` است که تابعی با نام `seoScore` در آن تعریف شده. امضای این تابع بهصورت زیر است:
```php
function seoScore(string $html): int
{
// TODO: Implement
}
```
این تابع باید با دریافت محتویات *HTML* یک صفحه در قالب یک رشته، آن را از لحاظ سئو بررسی کند و امتیازی در قالب یک عدد صحیح برگرداند.
برای بررسی صفحه و اختصاص امتیاز به آن باید به نکات زیر توجه کنید:
+ اگر صفحه دارای تگ `title` بود و تعداد کاراکترهای محتوای این تگ کوچکتر یا مساوی ۶۰ بود، ۱۰ امتیاز و اگر بیشتر از ۶۰ کاراکتر بود، ۷ امتیاز اضافه شود. **تضمین میشود** که این تگ در صورت وجود، بدون *attribute* و به شکل زیر خواهد بود:
```html
<title><mark title="عنوان صفحه">Page Title</mark></title>
```
+ اگر صفحه دارای تگ `meta` با نام `description` بود و تعداد کاراکترهای محتوای ویژگی `content` این تگ کوچکتر یا مساوی ۱۶۰ بود، ۱۰ امتیاز و اگر بیشتر از ۱۶۰ کاراکتر بود، ۷ امتیاز اضافه شود. **تضمین میشود** که این تگ در صورت وجود، با این ترتیب از *attribute* ها خواهد بود:
```html
<meta name="description" content="<mark title="محتویات description">description-content</mark>">
```
+ اگر صفحه دارای تگ `meta` با نام `viewport` بود، ۱۰ امتیاز اضافه شود. **تضمین میشود** که این تگ در صورت وجود، با این ترتیب از *attribute* ها خواهد بود:
```html
<meta name="viewport" content="<mark title="محتویات viewport">viewport-content</mark>">
```
+ اگر صفحه دارای تگ `meta` با نام `robots` بود، ۱۰ امتیاز اضافه شود. **تضمین میشود** که این تگ در صورت وجود، با این ترتیب از *attribute* ها خواهد بود:
```html
<meta name="robots" content="<mark title="محتویات robots">robots-content</mark>">
```
+ اگر صفحه دارای تگ `meta` با ویژگی `charset` بود، ۱۰ امتیاز اضافه شود. **تضمین میشود** که این تگ در صورت وجود، با این ترتیب از *attribute* ها خواهد بود:
```html
<meta charset="<mark title="مقدار charset">charset-value</mark>">
```
+ اگر صفحه دارای یک تگ `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
<?php
function seoScore(string $html): int
{
// TODO: Implement
}
$html =
'<!DOCTYPE html>
<html>
<head>
<mark title="۱۰ امتیاز"><meta charset="utf-8"></mark>
<mark title="۱۰ امتیاز"><meta name="viewport" content="width=device-width, initial-scale=1"></mark>
<mark title="۱۰ امتیاز"><title>Quera</title></mark>
<mark title="۱۰ امتیاز"><meta name="description" content="quera-codecup-college-magnet"></mark>
<mark title="۱۰ امتیاز"><meta name="robots" content="index, follow"></mark>
</head>
<body>
<mark title="۱۰ امتیاز"><header></mark>
<mark title="۱۰ امتیاز"><h1>Quera</h1></mark>
</header>
<mark title="۱۰ امتیاز"><section></mark>
<mark title="۵ امتیاز"><h2>Quera</h2></mark>
<mark title="۵ امتیاز"><h3>Quera</h3></mark>
<h3>Quera</h3>
<h3>Quera</h3>
</section>
<mark title="۱۰ امتیاز"><footer></mark>
<h2>Quera</h2>
</footer>
</body>
</html>';
echo seoScore($html);
```
خروجی باید بهصورت زیر باشد:
```
100
```
## آنچه باید آپلود کنید
یک فایل *PHP* که تابع `seoScore` در آن پیادهسازی شده است آپلود کنید.
اخیراً ایدهای به ذهن هوشنگ خطور کرده است که قصد دارد آن را پیادهسازی کند. ایده از این قرار است که او ابتدا فریمورک کوچکی را پیادهسازی کند و سپس یک سیستم لاگ را برای آن پیادهسازی کند. او این سیستم را *لاگچری* نامیده است.
او قسمتهایی از این پروژه را انجام داده، اما در پیادهسازی بعضی از قسمتها به مشکل خورده است. شما باید برای قسمتهایی از پروژه که او به مشکل خورده است به او کمک کنید.
# جزئیات پروژه
پروژهی اولیه را از [این لینک](/contest/assignments/35047/download_problem_initial_project/121245/) دانلود کنید.
<details class="grey">
<summary>ساختار فایلها</summary>
```
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
```
</details>
<details class="brown">
<summary>راهاندازی پروژه</summary>
**برای اجرای پروژه، باید `php` و `composer` را از قبل نصب کرده باشید.**
+ پروژهی اولیه را دانلود و از حالت فشرده خارج کنید.
+ دستور `composer install` را در پوشهی اصلی پروژه برای نصب نیازمندیها اجرا کنید.
+ دستور `php -S 127.0.0.1:8000 -t public` را در پوشهی اصلی پروژه اجرا کنید. پروژه از طریق آدرس http://127.0.0.1:8000 در دسترس خواهد بود.
</details>
در اولین گام باید **کدهای این پروژه را مطالعه کرده و با منطق پروژه آشنا شوید**. در ادامه، باید تغییراتی که در ادامه ذکر شده است را در پروژه اعمال کنید.
ابتدا باید کلاس `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
```
در قالب بالا `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
```
با ارسال درخواست به آدرس `/`، کاربر باید با صفحهی زیر مواجه شود:
![صفحهی اصلی](https://quera.ir/qbox/view/MELdAEuhqj/logtury.png)
## نکات
+ این پروژه از استاندارد [*PSR-4*](https://www.php-fig.org/psr/psr-4/) برای *autoloading* کلاسها استفاده میکند.
+ شما تنها مجاز به اعمال تغییرات در پوشهی `app` و فایلهای `core/Logger.php` و `core/routes.php` هستید.
## آنچه باید آپلود کنید
پس از اعمال تغییرات، پوشههای `app` و `core` را زیپ کرده و آپلود کنید.
> هنگام انجام کارها یا آن ها را با عشق انجام دهید یا هرگز انجام ندهید.
این جمله از **گاندی** رضا را به این فکر فرو برده است که فکری برای انجام بسیاری از کارهای تکراری که باید بهطور متناوب انجام دهد بکند. بهعنوان مثال او از خط فرمان (*command-line*) خیلی استفاده میکند و همیشه آرزو داشت تا دستوراتی را خودش ایجاد و از آنها استفاده کند.
در این سؤال باید بههمراه او این آرزو را برآورده کنید.
## جزئیات پروژه
پروژهی اولیه را از [این لینک](/contest/assignments/35047/download_problem_initial_project/121220/) دانلود کنید.
<details class="grey">
<summary>ساختار فایلها</summary>
```
qcli
├── core
│ ├── Commands
│ └── Command.php
├── stubs
│ └── command.stub
├── test
│ └── QCliSampleTest.php
├── composer.json
├── composer.lock
└── qcli
```
</details>
<details class="brown">
<summary>راهاندازی پروژه</summary>
**برای اجرای پروژه، باید `php` و `composer` را از قبل نصب کرده باشید.**
+ پروژهی اولیه را دانلود و از حالت فشرده خارج کنید.
+ دستور `composer install` را در پوشهی اصلی پروژه برای نصب نیازمندیها اجرا کنید.
</details>
در دایرکتوری اصلی پروژه، فایلی به نام `qcli` وجود دارد که یک اسکریپت *PHP* است. از این فایل برای هندل کردن دستورات استفاده میشود. این فایل پس از دریافت دستور، پارامترهای ورودی را برای اجرا به متد `run` کلاس `QCli\Command` ارسال میکند.
در ابتدا باید برنامه را طوری پیادهسازی کنید که دستور `make:command <mark title="نام کلاس">name</mark> <mark title="امضای دستور">sign</mark>` بهصورت پیشفرض در برنامه موجود باشد. `name` نام کلاس دستور و `sign` امضای دستور است. وظیفهی این دستور این است که دستورات دلخواه را در دایرکتوری `core/Commands` ایجاد کند. قالب دستوراتی که ایجاد میشوند باید مطابق محتویات فایل `stubs/command.stub` باشد:
```php stubs/command.stub php
<?php
namespace QCli\Commands;
class <mark title="نام کلاس">{{ name }}</mark>
{
protected string $signature = '<mark title="امضای دستور">{{ sign }}</mark>';
protected string $description = '<mark title="نام کلاس">{{ name }}</mark> description';
public function handle()
{
echo 'Command ' . $this->signature . ' is ready to implement';
}
}
```
فرض کنید دستور زیر در خط فرمان وارد میشود:
```shell
php qcli make:command <mark title="نام کلاس">CustomCommand</mark> <mark title="امضای دستور">custom:command</mark>
```
با اجرای دستور فوق، باید فایل `CustomCommand.php` در مسیر `core/Commands` ساخته شود:
```php core/Commands/CustomCommand.php 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';
}
}
```
همچنین ممکن است کلاسهایی بهصورت دستی (بدون استفاده از دستور پیشفرض `make:command`) در مسیر `core/Commands` ایجاد شوند. برنامه باید بتواند این دستورات را نیز شناسایی کند. **تضمین میشود** که این کلاسها نیز مطابق محتویات فایل `stubs/command.stub` هستند.
اگر دستور ایجادشده در خط فرمان وارد شود، باید متد `handle` از کلاس دستور اجرا شود، یعنی در مثال قبل اگر دستور زیر وارد شود:
```shell
php qcli <mark title="امضای دستور">custom:command</mark>
```
باید عبارت `Command custom:command is ready to implement` چاپ شود.
## نکات
+ **تضمین میشود** که دو دستور با نام کلاس یا امضای یکسان ایجاد نخواهد شد.
+ این پروژه از استاندارد [*PSR-4*](https://www.php-fig.org/psr/psr-4/) برای *autoloading* کلاسها استفاده میکند.
+ شما تنها مجاز به اعمال تغییرات در دایرکتوری `core` هستید. میتوانید فایلها و دایرکتوریهای جدیدی نیز در این دایرکتوری ایجاد کنید.
+ در صورت نیاز، میتوانید متدهای دیگری نیز در کلاس `QCli\Command` پیادهسازی کنید.
## آنچه باید آپلود کنید
پس از اعمال تغییرات، پوشهی `core` را زیپ کرده و آپلود کنید.