سینا به تازگی شروع به برنامه نویسی کرده و اخیرا مشغول بازبینی کدهای نوشته شده توسط احمد بود و نحوه نامگذاری متغیرهای او برای سینا جالب بود.
احمد متغیرهای خود را به صورت *camelCase* نامگذاری میکرد. به عنوان مثال نام یکی از متغیرهای احمد `counterVariable` بود.
حالا سینا قصد دارد قطعه کدی بنویسد که یک جمله را به عنوان ورودی دریافت کرده و آن را به صورت `camelCase` در خروجی نمایش دهد، اما چون تازه شروع به برنامه نویسی کرده از شما میخواهد تا این برنامه را برای او بنویسید.
## توضیحات ورودی
+ جملهای که باید به فرمت `camelCase` تبدیل شود در یک فایل به نام `input.txt` در کنار برنامه شما قرار خواهد داشت.
+ محتوای فایل تنها دارای یک خط می باشد.
+ در جمله مورد نظر چند کلمه که با کاراکتر *space* از هم جدا شدهاند وجود دارد. مانند نمونه زیر:
```
this is a sample sentence
```
همچنین ممکن است در ابتدا یا انتهای جمله تعدادی *space* اضافی وجود داشته باشد. مانند نمونه زیر:
```
some spaces exists in the beginning
```
## توضیحات خروجی
+ با فراخوانی فایل اسکریپت شما بایستی جمله موجود در فایل با فرمت `camelCase` در خروجی چاپ شود. لازم به ذکر است که نیازی به استفاده از ورودی و خروجی استاندارد (`STDIN` و `STDOUT`) نیست. کافی است خروجی نهایی را با استفاده از دستور `echo` چاپ کنید.
+ به عنوان یادآوری فرمت `camelCase` به این صورت است که همه کلمات جمله باید بدون فاصله به هم چسبانده شوند، در کلمه اول همه حروف آن کوچک باشد و سایر کلمات حرف اول آنها بزرگ و سایر حروفشان کوچک باشد. به عنوان مثال اگر محتوای فایل `input.txt` به صورت زیر باشد
```
first WORd seCONd woRd THIrd worD
```
با اجرای فایل شما، باید خروجی زیر (با استفاده از دستور `echo`) چاپ شود:
```
firstWordSecondWordThirdWord
```
## آن چه باید آپلود کنید
فایل پاسخ خود را با نام `camelCase.php` ذخیره کرده و به صورت فایل *ZIP* آپلود کنید.
فرایند *چکیده سازی* یا `hashing` معمولا برای تبدیل یک حجم داده به رشته کوچکی از عبارات استفاده میشود.
داده `hash`شده قابل برگشت نمیباشد.
یعنی نمیتوان از روی یک مقدار `hash` داده اصلی را حدس زد.
ولی با در اختیار داشتن داده اصلی و رشته `hash`شده میتوان اصالت داده اصلی را تعیین کرد.
بدین ترتیب یکی از مزایای استفاده از `hash` را میتوان کسب اطمینان از اصالت دادههای منتقل شده و عدم دستکاری توسط اشخاص دیگر عنوان کرد.
ما برای تضمین اصالت پیامهای کاربران در یک سیستم چت، میخواهیم ساختاری را ایجاد نماییم که با استفاده از آن بتوان یک پیام را با الگوریتمهای مختلف براساس انتخاب کاربران چکیده سازی نماییم.
# معرفی
پروژه اولیه را میتوانید از [اینجا](https://quera.ir/qbox/download/ZvpGAkMDS8/hashing.zip) دانلود کنید.
برای شروع میخواهیم امکان چکیده سازی پیامها با دو استراتژی `sha1` و `md5` امکان پذیر باشد.
اما در آینده ممکن است بخواهیم استراتژیهای بیشتری را پشتیبانی کنیم.
هر استراتژی باید یک کلاس متناظر داشته باشد که الگوریتم چکیده سازی مختص خود را پیاده سازی کرده باشد.
ما برای پشتیبانی استراتژیهای فعلی، دو کلاس `SHA1Hash` و `MD5Hash` را ایجاد نمودهایم.
### فایل `HashFactory.php`
برای مدیریت استراتژیهای ممکن، نیاز به کلاسی داریم که استراتژیهای موجود را به همراه کلاسهای متناظرشان، مدیریت کند.
برنامه باید به گونهای پیاده سازی شود که اگر استراتژیهای موجود به بیش از چند ده مورد افزایش پیدا کرد، باز هم مدیریت استراتژیهای موجود، به سادگی قابل انجام باشد.
برای انجام این کار یک کلاس به نام `HashFactory` ایجاد کردهایم.
وظیفه این کلاس ایجاد کلاسهایی هست که چکیده سازی را با الگوریتمهای مشخص شده انجام میدهند.
این کلاس شامل دو متد میباشد.
1. `register`:
این متد، دو پارامتر میگیرد که اولی نام الگوریتم چکیده سازی (مثلا `sha1`) و دومی یک نمونه از کلاسی است که وظیفه چکیده سازی با این الگوریتم را برعهده دارد.
2. `make`:
این تابع نام یک الگوریتم چکیده سازی را ورودی میگیرد و در خروجی کلاسی را برمیگرداند که با استفاده از این الگوریتم چکیده سازی میکند.
در ابتدای برنامه، الگوریتمهای پشتیبانی شده توسط برنامه را به همراه یک نمونه از شی متناظر این استراتژی را در این کلاس ثبت میکنیم. ( با استفاده از متد `register`).
سپس در مرحله بعد، شیای که توانایی چکیده سازی با استراتژی انتخاب شده توسط کاربر را دارد، از این کلاس تحویل میگیریم. (متد `make`)
### فایل `HashStrategy.php`
اینترفیسی طراحی کردهایم که تمام کلاسهای چکیده سازی موظف هستند، آن را پیاده سازی نمایند.
این اینترفیس تنها شامل تابعی به نام `hash` میباشد.
این تابع یک رشته را به عنوان ورودی میگیرد و نتیجه چکیده سازی توسط الگوریتم متناظر را، خروجی میدهد.
### فایلهای `SHA1Hash.php` و `MD5Hash.php`
هرکدام از استراتژیهای چکیده سازی باید از طریق یک کلاس پیاده سازی شوند. این کلاسها اینترفیس `HashStrategy` را پیاده سازی میکنند.
پیاده سازی این کلاسها باید از الگوی *Singleton* پیروی نماید.
به این معنی که در طول اجرای برنامه تنها یک شی از این کلاس قابل نمونه سازی باشد.
این دو کلاس باید متد `hash` را به گونهای پیاده سازی کنند که توانایی چکیده سازی مقدار ورودی با استفاده از الگوریتم متناظرشان را داشته باشد.
با توجه به وجود کلاس `HashFactory` برای مدیریت استراتژیهای مختلف، این کلاسها را به گونهای محدود کنید، که در خارج از کلاس قابل نمونه سازی با استفاده از عبارت `new` نباشند.
تنها راه دسترسی به اشیا نمونه سازی شده از این کلاسها باید متد `getInstance` باشد.
همچنین باید متد `getInstance` را به گونهای پیاده سازی نمایید که در طول برنامه، پس از چندین بار فراخوانی، تنها یک شی از این کلاس بسازد و در فراخوانیهای بعدی همان شیای که قبلا ساخته شده برگردانده شود.
# پیاده سازی
### فایل `HashFactory.php`
متد `register` و `make` را به گونهای پیاده سازی نمایید که بعد از فراخوانی به شکل زیر، بتواند یک نمونه از شیای که قابلیت `hash` کردن داده با الگوریتم مناسب را دارد، برگرداند.
```php
$factory = new HashFactory();
$factory->register('sha1', SHA1Hash::getInstance());
$factory->register('md5', MD5Hash::getInstance());
$hasher = $factory->make($_GET['strategy']);
```
### فایلهای `SHA1Hash.php` و `MD5Hash.php`
1. تابع سازنده کلاس را به گونهای تغییر دهید که امکان نمونه سازی از کلاس، در خارج از آن، امکان پذیر نباشد.
2. متد `getInstance` را به گونهای پیاده سازی کنید که با هربار فراخوانی تنها یک نمونه از کلاس ساخته شده را، یک شی نمونه سازی شده واحد را برگرداند.
3. تابع `hash` را برای هر استراتژی به گونهای پیاده سازی کنید، که با الگوریتم متناسب همان استراتژی، عملیات چکیده سازی را انجام دهد.
کلاسها باید به گونهای پیاده سازی شوند، که با هر بار اجرای فایل `index.php` رشته موجود در متغیر `$_GET['data']` با استفاده از استراتژی موجود در متغیر `$_GET['strategy']`، چکیده سازی شده و رشته حاصل در صفحه چاپ شود.
همچنین در صورتی که استراتژی موجود، در برنامه پشتیبانی نشود، باید یک `Exception` با پیام `Strategy Not Supported` پرتاب شود و اجرای برنامه خاتمه یابد. مثلا اگر کاربر درخواستی با مقدار `$_GET['strategy'] = 'sha256'` ارسال کند، برنامه باید این `Exception` را پرتاب کند.
توجه کنید در هر فایل نباید بیش از یک کلاس تعریف شود.
شما باید در کلاسهای مختلف، تنها بخشهایی که کامنت `Implement` را دارند، توسعه دهید.
همچنین، توجه کنید که فایل ها به صورت خودکار `require` میشوند. شما در هیچ کدام از فایل ها نیازی به `require` یا `include` ندارید.
در نهایت فایلهای زیر را در یک فایل *ZIP* قرار داده و آپلود نمایید. نام فایل *ZIP* اهمیتی ندارد.
1. `HashFactory.php`
2. `MD5Hash.php`
3. `SHA1Hash.php`
توجه کنید که فقط حق تغییر سه فایل بالا را دارید و نمیتوانید محتوای دیگر فایلها را تغییر دهید.
برای انجام عملیات `Authentication` روشهای متعددی وجود دارد. همچنین برای یادآوری و جلوگیری از تکرار این عملیات مکانیزمهای مختلفی طراحی شده است. در سالهای گذشته (و همچنین در حال حاضر) یکی از روشهای متداول برای به خاطرسپاری عملیات تشخیص هویت استفاده از `Cookie`ها بوده است.
اما با طراحی استاندارد `RFC 7519` و پیاده سازی آن در زبانهای مختلف، این روش محبوبیت و کاربرد زیادی پیدا کرده است.
در این سوال از شما میخواهیم که یک روال اعتبارسنجی کامل با این روش را پیاده سازی نمایید.
## ساختار پروژه
+ کل کدهای پروژه در یک فایل به نام `jwt.php` نوشته خواهد شد.
+ ساختار این فایل بسیار ساده بوده و تنها دارای ۲ تابع می باشد که بایستی با شرایطی که در قسمت بعد ذکر شده است تکمیل شوند.
+ فایل `users.json` حاوی یک آرایه از دادههای آزمایشی برای کاربران می باشد که برای انجام عملیات `Authentication` از محتوای این فایل باید استفاده کنید.
+ پروژه اولیه را میتوانید از [اینجا](https://quera.ir/qbox/download/UVZr1TAyFu/jwt.zip) دانلود کنید.
## توضیحات پروژه
+ برای تست و اجرای پروژه بهتر است با اجرای دستور `php -S 127.0.0.1:5555 -t ./` در پوشه برنامه از سرور `builtin` استفاده کنید (پورت و آدرس قابل تغییر است).
+ تابع `checkLogin` را به صورتی تکمیل کنید که با ارسال پارامترهای `username` و `password` از طریق متد `POST`، این دو پارامتر با اطلاعات موجود در فایل `users.json` تطبیق داده شده و در صورتی که اطلاعات صحیح باشد خروجی زیر با فرمت *JSON* چاپ شود:
```json
{"type":"login_success","token":"JWT_TOKEN"}
```
و در صورتیکه پارامترهای وارد شده با هیچ یک از اطلاعات موجود در فایل مطابقت نداشته باشد خروجی زیر چاپ شود:
```json
{"type":"login_failure","token":""}
```
> واضح است که به جای عبارت `JWT_TOKEN` باید توکن معتبر و صحیح جایگذاری شود.
+ در نظر داشته باشید که `JWT token` تولید شده دارای زمان بوده و پس از گذشت مدت زمان معینی که بر اساس واحد زمان ثانیه، در ثابت `TOKEN_LIFETIME` در بالای فایل `jwt.php` ذکر شده است بایستی منقضی شود. لازم به ذکر است که این خط را از بالای فایل نباید حذف کنید و نام ثابت را هم نباید تغییر دهید (شما می توانید عدد زمان را تغییر دهید، این عدد در زمان ارزیابی پاسخ هم تغییر خواهد کرد).
+ با فراخوانی تابع `getData` باید حالتهای زیر در نظر گرفته شود :
- اگر `token` اعتبار سنجی در `header` درخواست وجود نداشته باشد یا طول آن `0` باشد پاسخ اسکریپت `403 Forbidden` بوده و `body` باید تهی باشد. یعنی هیچ متن یا کاراکتری در خروجی نداشته باشیم و فقط این موضوع از طریق `header` به کلاینت اطلاع داده می شود.
- اگر `token` نا معتبری به سمت اسکریپت ارسال شود بایستی `header` به صورت `401 Unauthorized` بوده و در `body` عبارت `INVALID_TOKEN` به عنوان خروجی نمایش داده شود.
- اگر `token` منقضی شدهای به سمت اسکریپت ارسال شود بایستی `header` به صورت `401 Unauthorized` بوده و در `body` عبارت `EXPIRED_TOKEN` به عنوان خروجی نمایش داده شود.
- اگر `token` صحیحی به سمت اسکریپت ارسال شود بایستی المان `keys` مربوط به کاربر صاحب `token` به صورت `json encoded` در خروجی چاپ شود (نیازی به تغییر `header` پاسخ نیست).
توجه داشته باشید که در موارد بالا `HTTP Response Code` و`HTTP Response Verb` بررسی خواهد شد.
برای پاسخ به این سوال می تواند از پکیج های `composer` هم استفاده کنید (هرچند که الزامی نیست و بدون نیاز به پکیج ها هم سوال قابل حل است) اما در صورت تمایل فایل `composer.json` را همراه با فایل `jwt.php` فشرده کنید و به عنوان جواب ارسال کنید.
## آن چه باید آپلود کنید
فایل پاسخ خود را با نام `jwt.php` ذخیره کرده و به صورت فایل *ZIP* آپلود کنید.
میخواهیم برای یک سایت جستجوی فیلم، سامانهای طراحی کنیم که کاربران بتوانند برای فیلمهای موجود نقد و بررسی بنویسند. کاربران می توانند در هر نقد و بررسی، براساس یک یا چند پارامتر به هر فیلم امتیاز دهند. این پارامترها با توجه به ژانر هر فیلم متغیر میباشد.
مثلا برای یک فیلم از ژانر درام، میتوانیم به هرکدام از پارامترهای زیر امتیاز 1 تا 5 بدهیم.
1. شخصیت پردازی در داستان
2. روند منطقی داستان پردازی
3. پایان بندی قابل قبول
توجه کنید که این پارامترها برای هر ژانر کاملا متفاوت بوده و هر پارامتر نمیتواند برای بیش از یک ژانر در نظر گرفته شود.
هر شخص تنها یک بار میتواند در این نطرسنجی شرکت نماید. در صورتی که شخصی بیش از یکبار درخواست ثبت رای را ارسال کند، سیستم باید پیغام `Duplicate Vote` را به عنوان خروجی برگرداند. برای ذخیره سازی فیلمهای نقد و بررسی شده توسط کاربر میتوانید از کوکی استفاده کنید.
پایگاه داده از نوع `Sqlite3` است و ساختار طراحی شده برای آن شامل جدولهای زیر میباشد.
### جدول `parameters`
| ملاحضات | تعریف | نوع | اسم ستون |
|:-:|:-:|:-:|:-:|
| `PRIMARY KEY` | شناسهی پارامتر | `integer` | `id` |
| `NOT NULL UNIQUE` | عنوان پارامتر | `text` | `title` |
| `NOT NULL` | ژانر پارامتر | `text` | `genre` |
### جدول `films`
| ملاحضات | تعریف | نوع | اسم ستون |
|:-:|:-:|:-:|:-:|
| `PRIMARY KEY` | شناسهی فیلم | `integer` | `id` |
| `NOT NULL UNIQUE` | عنوان فیلم | `text` | `title` |
| `NOT NULL` | ژانر فیلم | `text` | `genre` |
### جدول `votes`
| ملاحضات | تعریف | نوع | اسم ستون |
|:-:|:-:|:-:|:-:|
| `NOT NULL` | شناسهی فیلم | `integer` | `film_id` |
| `NOT NULL` | عنوان پارامتر | `integer` | `parameter_id` |
| `NOT NULL` | امتیاز | `integer` | `score` |
## مراحل پیاده سازی
پروژه اولیه را میتوانید از [اینجا](https://quera.ir/qbox/download/fN4cUNniqD/review-system.zip) دانلود کنید.
### آماده سازی
فایل `functions.php`
1. متد `is_installed` را به گونهای پیاده سازی کنید که وضعیت نصب شده بودن سیستم را بررسی نماید. راهکار تعیین وضعیت نصب، برعهده شما می باشد(در مورد نحوه نصب کردن توضیح داده میشود).
2. متد `is_request_get` را به گونهای پیاده سازی کنید که مشخص نماید که آیا درخواست فعلی با استفاده از متد `GET` ایجاد شده است یا خیر.
3. متد `is_request_post` را به گونهای پیاده سازی کنید که مشخص نماید که آیا درخواست فعلی با استفاده از متد `POST` ایجاد شده است یا خیر.
### نصب
فایل `install.php` را به گونهای تغییر دهید که ابتدا یک دیتابیس از نوع `Sqlite3` به نام `_db.sqlite` در کنار فایل `index.php` ایجاد نماید.
سپس جداول `films` ، `parameters` و `votes` را با استفاده از ساختار تعیین شده بالا بر روی آن ایجاد کند.
در مرحله بعد برنامه نصب باید اطلاعات اولیه فیلمها و پارامترهای نقد و بررسی را از فایلهای _JSON_ موجود در پوشه `data` بخواند و وارد جدولهای پایگاه داده نماید.
فولدر `data` دارای دو فایل متفاوت می باشد.
1. `films.json`: اطلاعات فیلمهای قابل نقد و بررسی در این فایل قرار دارد. تابع `read_films` وظیفه خواندن این فایل و بازگرداندن اطلاعات به صورت یک آرایه را بر عهده دارد.
2. `parameters.json`: اطلاعات پارامترهای قابل نقد و بررسی در این فایل قرار دارد. تابع `read_parameters` وظیفه خواندن این فایل و بازگرداندن اطلاعات به صورت یک آرایه را برعهده دارد.
توابع `read_films` و `read_parameters` را به گونه ای پیاده سازی نمایید، که اطلاعات موجود در فایل _JSON_ را به صورت یک آرایه `php` بازگرداند.
توجه کنید که فایل `install.php` تنها یک بار قابلیت اجرا دارد. درصورتی که کاربر چندین بار این فایل را اجرا نماید، باید خطای `Already installed` به کاربر نمایش داده شود.
### دریافت پارامترهای نقد و بررسی
فایل `vote.php`
این فایل ID یک فیلم را از طریق متغیر `$_GET['film_id']` دریافت میکند و در پاسخ باید لیستی از پارامترهای قابل رای دهی برای این فیلم، (با توجه به ژانر) را در آرایهای به شکل نمونه تصادفی زیر برگرداند:
```json
[
[
id: 1,
title: ‘عنوان پارامتر اول’,
],
[
id: 2,
title: ‘عنوان پارامتر دوم,
],
[
id: 3,
title: ‘عنوان پارامتر سوم,
],
]
```
متدها:
+ `get_parameters($film_id)`: این تابع `ID` یک فیلم را به عنوان پارامتر می گیرد و پارامترهای قابل نقد و بررسی برای آن فیلم را به صورت ذکر شده باز می گرداند.
+ `has_voted($film_id)`: این تابع `ID` یک فیلم را به عنوان پارامتر می گیرد و بررسی می کند که آیا کاربر فعلی قبلا برای این فیلم رای خود را ثبت کرده است یاخیر.
### ثبت نقد و بررسی
فایل `vote.php`
این فایل وظیفه دریافت رایهای کاربر و ثبت آنها در پایگاه داده را بر عهده دارد. اطلاعات دریافتی این فایل از طریق متغیر `$_POST` شامل موارد زیر میباشد.
+ `$_POST['film_id']`: ID فیلمی که نقد و بررسی برای آن ارسال شده است
+ `$_POST['scores']`: آرای ثبت شده کاربر به تفکیک پارامترها
ساختار داده امتیازات به صورت زیر میباشد:
```json
[
Parameter_id: Score,
]
```
یک نمونه از متغیر `$_POST['scores']` به صورت زیر میباشد:
```json
[
1: 5,
2: 3,
3: 1
]
```
شما باید تابع `submit_vote($film_id, $scores)` را بگونه ای تغییر دهید که امتیازات کاربر را ثبت نماید.
\*نکته: توجه کنید که اگر فایل `vote.php` با متد `GET`فراخوانی کنیم باید پارامترهای قابل بررسی را نمایش بدهد و درصورتی که با متد `POST` فراخوانی کنیم باید نقد و بررسی را ثبت نماید.
توجه کنید که امتیاز هر پارامتر باید مقداری بین 1 تا 5 باشد. در صورتی که کاربر اعدادی بزرگتر از `5` و یا کوچکتر از `1` را به عنوان رای ارسال کند، سیستم باید به صورت اتوماتیک رای کاربر را در بازه مشخص شده اصلاح نماید. مثلا اگر کاربر برای یک پارامتر امتیاز `7` را وارد کرد، سیستم باید حداکثر امتیار ممکن یعنی `5` را به آن رای اختصاص دهد. و اگر کاربری امتیاز `0` را برای پارامتری ارسال کرد، سیستم باید حداقل امتیاز ممکن یعنی `1` را به آن رای اختصاص دهد.
### نمایش لیست فیلمها
فایل `index.php`
متد `get_films` موجود در این فایل را به گونهای پیاده سازی نمایید که یک آرایه از فیلمهای موجود در جدول `films` به همراه تعداد آرای ثبت شده برای هر فیلم و همچنین میانگین آرای ثبت شده برای هر فیلم را برگرداند.
تعداد رایهای ثبت شده برای هر فیلم برابر ردیف های موجود در جدول `votes` میباشد، به صورتی که `film_id` برابر با `ID` فیلم مورد نظر باشد.
همجنین میانگین رایهای ثبت شده برای یک فیلم، برابر میانگین مقادیر فیلد `score` در جدول `votes` می باشد، به صورتی که `film_id` برابر با `ID` فیلم مورد نظر باشد.
ساختار خروجی این متد باید به شکل زیر باشد:
```json
[
[
'film_id'=> `ID فیلم`,
'title'=> `عنوان فیلم`,
'votes_count'=> `تعداد رایهای ثبت شده`,
'average_score'=> `میانگین رایهای ثبت شده`,
],
[
'film_id'=> `ID فیلم`,
'title'=> `عنوان فیلم`,
'votes_count'=> `تعداد رایهای ثبت شده`,
'average_score'=> `میانگین رایهای ثبت شده`,
],
]
```
### جواب
در انتها فایل های زیر را به صورت یک فایل _zip_ آپلود نمایید. نام فایل _zip_ اهمیتی ندارد.
+ `functions.php`
+ `index.php`
+ `install.php`
+ `vote.php`
PHP - سامانه ثبت نقد و بررسی
**کد شما باید روی نسخهی استاندارد MySQL قابل اجرا باشد**،
برای چک کردن سینتکس کد SQL خود میتوانید از **[این وبسایت](https://www.eversql.com/sql-syntax-check-validator/)** کمک بگیرید.
---
بخشی از پایگاه دادهی سامانهی حسابداری یک شرکت بازرگانی به شما دادهشده است.
این پایگاه داده در حال حاضر شامل ۸ جدول است. این جدولها عبارتند از:
**مشتریها**، **دستهبندیهای محصولات**، **کارمندان**، **سفارشات**، **جزئیات سفارشات**، **محصولات**، **تهیه کنندهها** و **ارسال کنندهها**.
---
هر مشتری دارای نام، نام رابط، آدرس، شهر، کد پستی و کشور است.
در اینجا شمای جدول `Customers` را آوردهایم:
|اسم ستون|نوع|تعریف|ملاحضات|
|:-:|:-:|:-:|:-:|
|`CustomerID`|`int`|شناسهی مشتری|`primary key`|
|`CustomerName`|`varchar`|نام مشتری||
|`ContactName`|`varchar`|نام رابط||
|`Address`|`varchar`|آدرس||
|`City`|`varchar`|شهر||
|`PostalCode`|`varchar`|کد پستی||
|`Country`|`varchar`|کشور||
هر دستهبندی دارای نام دسته و توضیحات آن است.
در اینجا شمای جدول `Categories` را آوردهایم:
|اسم ستون|نوع|تعریف|ملاحضات|
|:-:|:-:|:-:|:-:|
|`CategoryID`|`int`|شناسهی دسته|`primary key`|
|`CategoryName`|`varchar`|نام دسته||
|`Description`|`varchar`|توضیحات||
هر کارمند دارای نام، نام خانوادگی، تاریخ تولد، تصویر پرسنلی و توضیحات است.
در اینجا شمای جدول `Employees` را آوردهایم:
|اسم ستون|نوع|تعریف|ملاحضات|
|:-:|:-:|:-:|:-:|
|`EmployeeID`|`int`|شناسهی کارمند|`primary key`|
|`LastName`|`varchar`|نام خانوادگی||
|`FirstName`|`varchar`|نام||
|`BirthDate`|`date`|تاریخ تولد با قالب `YYYYMMDD`||
|`Photo`|`varchar`|عکس پرسنلی||
|`Notes`|`text`|توضیحات||
هر ارسالکننده دارای نام و تلفن است.
در اینجا شمای جدول `Shippers` را آوردهایم:
|اسم ستون|نوع|تعریف|ملاحضات|
|:-:|:-:|:-:|:-:|
|`ShipperID`|`int`|شناسهی ارسال کننده|`primary key`|
|`ShipperName`|`varchar`|نام ارسال کننده||
|`Phone`|`varchar`|تلفن||
هر سفارش دارای یک مشتری، یک کارمند ثبت کنندهی سفارش، یک ارسال کننده و تاریخ ثبت سفارش است.
در اینجا شمای جدول `Orders` را آوردهایم:
|اسم ستون|نوع|تعریف|ملاحضات|
|:-:|:-:|:-:|:-:|
|`OrderID`|`int`|شناسهی سفارش|`primary key`|
|`CustomerID`|`int`|شناسهی مشتری|`foreign key (Customers)`|
|`EmployeeID`|`int`|شناسهی کارمند|`foreign key (Employees)`|
|`OrderDate`|`date`|تاریخ ثبت سفارش با قالب `YYYYMMDD`||
|`ShipperID`|`int`|شناسهی ارسال کننده|`foreign key (Shippers)`|
جدول جزئیات سفارش مشخص میکند هر سفارش دارای چه محصولاتی است. هر جزء سفارش دارای یک سفارش، یک محصول و تعداد آن محصول در سفارش است.
در اینجا شمای جدول `OrderDetails` را آوردهایم:
|اسم ستون|نوع|تعریف|ملاحضات|
|:-:|:-:|:-:|:-:|
|`OrderDetailID`|`int`|شناسهی جزء سفارش|`primary key`|
|`OrderID`|`int`|شناسهی سفارش|`foerign key (Orders)`|
|`ProductID`|`int`|شناسهی محصول|`foreign key (Products)`|
|`Quantity`|`int`|تعداد||
هر محصول دارای نام، تهیهکننده، دستهبندی، واحد و قیمت به ازای هر واحد است.
در اینجا شمای جدول `Products` را آوردهایم:
|اسم ستون|نوع|تعریف|ملاحضات|
|:-:|:-:|:-:|:-:|
|`ProductID`|`int`|شناسهی محصول|`primary key`|
|`ProductName`|`varchar`|نام محصول||
|`SupplierID`|`int`|شناسهی تهیهکننده|`foreign key (Suppliers)`|
|`CategoryID`|`int`|شناسهی دستهبندی|`foreign key (Categories)`|
|`Unit`|`varchar`|واحد||
|`Price`|`double`|قیمت واحد||
هر تهیهکننده دارای نام، نام رابط، آدرس، شهر، کد پستی، کشور و شماره تلفن است.
در اینجا شمای جدول `Suppliers` را آوردهایم:
|اسم ستون|نوع|تعریف|ملاحضات|
|:-:|:-:|:-:|:-:|
|`SupplierID`|`int`|شناسهی تهیهکننده|`primary key`|
|`SupplierName`|`varchar`|نام تهیهکننده||
|`ContactName`|`varchar`|نام رابط||
|`Address`|`varchar`|آدرس||
|`City`|`varchar`|شهر||
|`PostalCode`|`varchar`|کد پستی||
|`Country`|`varchar`|کشور||
|`Phone`|`varchar`|تلفن||
---
## مطلوبات
کوئریهای *SQL* خواستهشده از شما موارد زیر است: (توجه کنید که هر کوئری نمرهای جداگانه دارد و اگر کوئری یک قسمت را نتوانستید بزنید، کوئریهایی که حل کردید را بفرستید و قسمت آن کوئری را خالی بگذارید.)
#### بخش ۱
تمام اطلاعات جدول `Customers` را از تمام مشتریانی که نامشان با حرف `A` شروع میشود، به ترتیب صعودی بر اساس نام مشتری گزارش کنید.
#### بخش ۲
اطلاعات مشتریان تمام کشورهایی را که کمتر از ۵ مشتری متمایز دارند، از جدول `Customers` پاک کنید.
#### بخش ۳
نام تمام مشتریهایی که حداقل یکی از ۵ ارزانترین کالای موجود را سفارش دادهاند را به ترتیب صعودی الفبایی در قالب ستون `CustomerName` گزارش کنید.
#### بخش ۴
۱۰ عدد متمایز از بیشترین تعداد واحد فروش محصولات در یک بازهی یک ماهه (شروع از روز اول ماه و پایان در روز آخر ماه) را مشخص کنید. ۱۰ عدد متمایز به ترتیب نزولی مرتب شده را در قالب ستون `Sales` گزارش کنید.
##### توضیح
هر نوع کالا در هر ماه تعدادی فروش داشته است. بایستی تعداد واحدهای فروش کالاهای مختلف در ماههای مختلف را به صورت نزولی مرتب کنید و ۱۰ تای اول متمایز را گزارش کنید.
---
## روش پیادهسازی
کد خود را در قالب زیر، در یک فایل با نام `code.sql` قرار دهید و آن را ارسال کنید.
```
-- Section1
your first query here
-- Section2
your second query here
-- Section3
your third query here
-- Section4
your fourth query here
```