ظاهر کلی برنامه بدین صورت است:
![ظاهر برنامه](https://quera.ir/qbox/view/qYGzJzNp1e/poll.gif)
# پروژه اولیه
پروژه اولیه را از
[این لینک](/contest/assignments/35059/download_problem_initial_project/125903/)
دانلود کنید.
<details class="green">
<summary>
ساختار فایلهای پروژه
</summary>
```
poll-creator
├── public
│ ├── favicon.ico
│ └── index.html
├── src
│ ├── __tests__
│ │ └── sample.test.js
│ ├── assets
│ │ ├── images
│ │ │ ├── Clapping-Hands-Emoji.png
│ │ │ ├── Confused Face Emoji.png
│ │ │ ├── Heart Eyes Emoji.png
│ │ │ ├── Neutral Face Emoji.png
│ │ │ ├── Ok Hand Sign Emoji.png
│ │ │ ├── Slightly Smiling Face Emoji.png
│ │ │ ├── Smiling Face with Halo.png
│ │ │ ├── Very Angry Emoji.png
│ │ │ └── Very Mad Emoji.png
│ │ ├── styles
│ │ │ ├── accordion.css
│ │ │ ├── app.css
│ │ │ ├── controls.css
│ │ │ └── preview.css
│ │ └──
│ ├── components
│ │ ├── Accordion.js
│ │ ├── DescriptionItem.js
│ │ ├── EmojiCheckBoxItem.js
│ │ ├── PollCreator.js
│ │ ├── ShowEmoji.js
│ │ └── ShowPreviewEmoji.js
│ ├── App.js
│ └── index.js
├── package.json
└── package-lock.json
```
</details>
# جزئیات
کوئرا قصد دارد در سال 1400 از برنامه نویسان ایرانی در مورد بهترین های برنامه نویسی مانند بهترین فریمورک برای توسعه وب و... نظرسنجی کند.
برای مشارکت بیشتر، تصمیم بر این شد فرم نظرسنجی در بستر وب و با ایموجی ساخته بشه. نادر قسمتی از پروژه رو برای کوئرا انجام داد اما او رفیق نیمه راه بود و قبل کامل کردن پروژه فرار کرد.
حال ما از شما برای تکمیل این پروژه کمک میخواهیم.
# توضیحات
- اطلاعات ایموجی ها
اطلاعات ایموجی ها در آرایه ای از آبجکت ها ذخیره میشود. آبجکت ها شامل موارد زیر هستند:
```
{
title: عنوان ایموجی,
src: سورس عکس ایموجی,
isSelected: انتخاب شدن ایموجی در چک باکس,
description: توضیحات ایموجی
}
```
- کامپوننت ShowEmoji
از این کامپوننت برای نمایش ایموجی ها در قسمت `description` و `preview` استفاده کنید.
این کامپوننت سه پراپس به شرح زیر میگیرد:
+ پراپس `src` : سورس ایموجی مورد نظر میباشد.
+ پراپس `viewStyle` : یک استرینگ با مقادیر "description" یا "preview" که استایل مناسب هر قسمت را به ایموجی میدهد.
+ پراپس `name` : عنوان ایموجی را میگیرد که برابر `alt` ایموجی قرار میگیرد.
# مواردی که باید پیاده سازی شوند
<details class="blue">
<summary>
کامپوننت DescriptionItem
</summary>
این کامپوننت باید به گونه ای پیاده سازی شود که در صورت انتخاب شدن هر ایموجی، قسمتی شامل یک `input` و ایموجی مورد نظر، در قسمت description، مانند تصویر ساخته شود.
- این کامپوننت دو پراپس با عنوان های `emojis` و `setEmojis` میگیرد که مقادیر `state` ایموجی هاست.
- برای هر ایموجی انتخاب شده، باید یک `label` و یک `input` ایجاد شود.
+ لیبل باید ویژگی `htmlFor` برابر با عنوان ایموجی را داشته باشد.
+ برای نمایش ایموجی درون `label` از کامپوننت `ShowEmoji` استفاده کنید.
+ اینپوت باید `id` برابر با عنوان ایموجی داشته باشد.
- در صورت نوشته شدن درون `input` باید `state` آپدیت شده و مقدار وارد شده در آبجکت همان ایموجی ست شود.
- در صورت غیر فعال شدن ایموجی قسمت description مربوط به آن ایموجی باید از بین برود.
</details>
<details class="blue">
<summary>
کامپوننت ShowPreviewEmoji
</summary>
- این کامپوننت باید به گونه ای پیاده سازی شود که ایموجی های انتخاب شده و توضیحات مربوط به آنها را در صورت انتخاب شدن ایموجی، نمایش دهد.
- این کامپوننت یک پراپس با عنوان ٍ`emojis` میگیرد که اطلاعات ایموجی ها درون آرایه ای از آبجکت هاست.
- برای نمایش ایموجی ها از کامپوننت `ShowEmoji` استفاده کنید.
- برای نمایش توضیحات از تگ `div` استفاده کنید.
</details>
# نکات
شما تنها مجاز به اعمال تغییرات در فایل های `DescriptionItem.js` و `ShowPreviewEmoji.js`هستید.
برای ارسال پاسخ کل پروژه را zip کرده و ارسال کنید. دقت کنید که پوشهی node_modules در فایل ارسالی نباشد.
# پروژه اولیه
پروژه اولیه را از
[این لینک](/contest/assignments/35059/download_problem_initial_project/125886/)
دانلود کنید.
ساختار فایلهای این پروژه به صورت زیر است.
<details class="green">
<summary>
ساختار فایلهای این پروژه به این صورت است
</summary>
```
orderbook
├── public
│ ├── favicon.ico
│ └── index.html
├── src
│ ├── components
│ │ ├── OrderbookHeader.jsx
│ │ └── OrderbookListItem.jsx
│ ├── data
│ │ └── data.json
│ ├── functions
│ │ └── index.js
│ ├── styles
│ │ └── styles.css
│ ├── types
│ │ └── index.js
│ ├── App.jsx
│ ├── index.js
│ └── setupTests.js
└── package.json
```
</details>
<details class="brown">
<summary>
راهاندازی پروژه
</summary>
برای اجرای پروژه، باید`NodeJS` و `npm` را از قبل نصب کرده باشید.
- ابتدا پروژهی اولیه را دانلود و از حالت فشرده خارج کنید.
- در پوشهی `orderbook` ، دستور `npm install` را برای نصب نیازمندیها اجرا کنید.
- در همین پوشه، دستور `npm start` را برای راهاندازی پروژه اجرا کنید.
</details>
# جزئیات
ظاهر کلی برنامه بدین صورت است:
![ظاهر برنامه](https://quera.ir/qbox/view/6WUaNR8GLT/orderbook.PNG)
در مسابقه فرانتاند قبل با شمسالله آشنا شدید و به او کمک کردید که یک نمودار قیمت برای ارز دروغین خود بسازد و سر مردم را کلاه بگذارد (شریک جرم شدید!! :)) ). شمسالله با این کار پول خوبی به جیب زد و حالا قرار است صرافی خود را بهبود ببخشد. برای این کار قرار است شمسالله به صرافی خود یک جدول سفارشات (`orderbook`) اضافه کند تا مردم بیشتری به او و صرافیاش اعتماد کنند.
مثل گذشته شمسالله از شما میخواهد که در پیادهسازی فرانتاند این قسمت نیز به او کمک کنید.
#### جدول سفارشات (`orderbook`):
یکی از روشهایی که معاملهگران برای پیدا کردن نقطه ورود و خروج مناسب استفاده میکنند، خواندن جدول سفارشات است.
در این جدول سفارشهای انجام نشده در یک بازار مشخص میشود و مشخص میشود که در یک قیمت مشخص حجم سفارشها چقدر است.
برای مثال یک فرد در قیمت ۱۰۰ دلار :))) میخواهد یک بیتکوین بخرد. فرد دیگر در همین مقدار قیمت میخواهد دوتا بیتکوین بخرد. پس در قیمت ۱۰۰ دلار حجم سفارشها ۱ + ۲ = ۳ است. یعنی برای رد شدن از این قیمت باید حداقل ۳ بیتکوین خریداری شود. (توسط فرد یا افراد دیگر فروخته شود)
معاملهگران از این روش متوجه میشوند که حجم سفارشها در چه بازه قیمتی زیاد است و از آن برای پیاده کردن نقطه ورود و خروج مناسب استفاده میکنند.
این جدول از دو قسمت اصلی تشکیل شده است. یک قسمت برای سفارشهای خرید و یک قسمت برای سفارشهای فروش است. هر دو قسمت براساس بهترین قیمت مرتب میشوند. بهترین قیمت در قسمت خرید، بیشترین قیمت است و در قسمت فروش کمترین قیمت است. (منطقی بهنظر میرسه :)) )
#### اجزای جدول سفارشات (`orderbook`):
ستونهای هر قسمت از این جدول (قسمت خرید و فروش) عبارت است از: **قیمت** و **مقدار** و **مقدار کل**. قیمت مشخصکننده قیمت در آن سطر است. مقدار مشخصکننده مقدار عرضه شده از آن ارز در آن قیمت است. مقدار کل برابر است حجم عرضه شده از اولین سفارش (بهترین سفارش) تا آن سفارش بعلاوه خودش.
برای مثال در تصویر زیر در قیمت ۲۰۰ ریال ۳۷ تا ارز شمسالله توسط افرادی قرار است خریداری شود. در این قیمت چون بهترین قیمت است (در قسمت خرید بهترین قیمت، بیشترین قیمت است) حجم سفارشات قبل آن ۰ است. در قیمت ۱۹۹ ریال مقدار برابر ۳۲ است و حجم سفارشات قبل این قیمت برابر ۳۷ است. پس مقدار کل برابر ۳۲ + ۳۷ = ۶۹ میشود. به همین شکل برای باقی قیمتها و قسمت فروش اعداد محاسبه میشوند. در قسمت فروش بهترین قیمت کمترین قیمت است.
رنگ پشتزمینه نشاندهنده درصد مقدار کل در آن قیمت به بیشترین مقدار کل در هر دو قسمت جدول سفاراشات، که با توجه به تجمعی بدون این شاخص، بیشترین مقدار کل برابر است با بدترین قیمت (آخرین قیمت) هر قسمت (خرید و فروش).
![ظاهر برنامه](https://quera.ir/qbox/view/LAOHC7aC10/orderbook_1.PNG)
برای پیادهسازی این جدول شمسالله یک دیتا در اختیار شما قرار میدهد و از شما میخواهد که با استفاده از این دیتا، جدول سفارشات رو برای او پیادهسازی کنید.
#### وظیفه توسعهدهنده فرانتاند:
در این پروژه شما باید با استفاده از دیتای داده شده، جدول سفارشات این ارز را بسازید.
ساختار داده بهشکل زیر است:
```json
{
"quantity": number,
"price": number,
"type": "sell" | "buy"
}[]
```
که در آن *price* نشاندهنده قیمت، *quantity* نشاندهنده تعداد سفارشات در آن قیمت و *type* نشاندهنده نوع سفارش است که میتواند خرید (*buy*) یا فروش (*sell*) باشد.
این دیتا به کامپوننت `App.jsx` داده میشود.
#### مواردی که باید در این سوال رعایت کنید:
- شما باید ابتدا ساختار مورد نظر را بسازید و در قسمتهای مشخص شده در پروژه اولیه لیست سفارشهای خرید و فروش را با استفاده از کامپوننت `OrderbookListItem` نمایش دهید.
- این کامپوننت مقادیر زیر را به عنوان *props* دریافت میکند و **یک سطر از یک طرف جدول سفارشات را میسازد**.
شکل
پراپسهای دریافتی کامپوننت عبارت است از:
- *index*: نشاندهنده ایندکس آرایه است.
دقت کنید این ایندکس باید برابر ایندکس آرایه مرتب شده براساس بهترین قیمت در هر قسمت خرید و فروش باشد.
- *type*: این مقدار یا باید برابر با *buy* یا برابر با *sell* باشید.
- *price*: نشاندهنده قیمت آن سفارش است.
- *amount*: نشاندهنده حجم سفارشات در آن است.
دقت کنید فقط مقدار سفارشهای آن قیمت.
- *total*: نشاندهنده حجم کل سفارشات تا آن قیمت است.
دقت کنید مقدار سفارشهای آن قیمت بعلاوه حجم بقیه سفارشات تا آن قیمت. (براساس بهترین سفارش)
- *bgWidth*: نشاندهنده درصد رنگ پشتزمینه (درصد حجم سفارشات آن قیمت به بیشتر حجم) است.
**راهنمایی:** در هنگام محاسبه این عدد دقت کنید که شما باید مقدار کل در ردیف را به بیشترین مقدار کل (مقدار کل ردیف آخر قسمت خرید و فروش) حساب کنید. (براساس درصد) برای مثال اگر مقدار کل سفارشات خرید برابر ۱۰۰۰ و سفارشات فروش برابر ۱۵۰۰ باشد. شما باید مقدار کل هر ردیف تقسیم برای ۱۵۰۰ ضبدر ۱۰۰ کنید. برای مثال بالا این شاخص برای اولین سفارش خرید برابر `(۱۰۰ * ۳۷ / ۱۵۰۰)` است و شما باید برای کامپوننت مقدار `۲.۴۶%` را ارسال کنید. (دقت برابر دو رقم اعشار باشد)
# نکات
- برای ارسال پاسخ کل پروژه را _zip_ کرده و ارسال کنید. دقت کنید که پوشهی
_node_modules_ در فایل ارسالی نباشد.
# پروژه اولیه
پروژه اولیه را از
[این لینک](/contest/assignments/35059/download_problem_initial_project/125899/)
دانلود کنید.
<details class="green">
<summary>
ساختار فایلهای این پروژه به این صورت است
</summary>
```
snapp-shekarstoon
├── package.json
├── package-lock.json
├── public
│ └── index.html
├── server
│ ├── data
│ │ └── data.json
│ ├── index.js
│ ├── utils
│ │ └── router.js
│ └── views
│ └── index.html
└── src
├── API
│ └── <mark>index.js</mark>
├── App.js
├── Components
│ ├── Map
│ │ ├── <mark>Map.jsx</mark>
│ │ ├── Relative.jsx
│ │ └── Way.jsx
│ ├── MapWidget
│ │ ├── ClearButton.jsx
│ │ ├── <mark>Distance.jsx</mark>
│ │ ├── <mark>MapWidget.jsx</mark>
│ │ └── Row.jsx
│ ├── Marker.jsx
│ ├── Node
│ │ ├── Absolute.jsx
│ │ └── Node.jsx
│ └── UI
│ └── Title.jsx
├── hooks
│ ├── <mark>useAPI.jsx</mark>
│ ├── <mark>useMap.jsx</mark>
│ ├── <mark>useMarker.jsx</mark>
│ └── <mark>useNavigator.jsx</mark>
├── index.js
├── styles
│ ├── absolute.scss
│ ├── btn.scss
│ ├── marker.scss
│ ├── relative.scss
│ ├── row.scss
│ └── title.scss
└── utils
├── <mark>calcDistance.js</mark>
└── <mark>calcPositionCSS.js</mark>
```
</details>
<details class="brown">
<summary>
راه اندازی پروژه
</summary>
- ابتدا پروژهی اولیه را دانلود و از حالت فشرده خارج کنید.
- سپس با اجرای دستور `npm i` پکیج های مورد نیاز را نصب نمایید
- با اجرای دستور `node server/index.js` سرور را اجرا نمایید.
- با اجرای دستور `npm start` پروژه را اجرا نمایید
</details>
# جزئیات
![sample_gif](https://quera.ir/qbox/view/GfQRWosdgA/map_shekar.gif)
شکرستون شهری است به شدت رو به رشد به همین جهت مهیار تصمیم گرفته است که به این شهر نقل مکان کند که اندک سهمی در رشد این شهر نیز داشته باشد. اما در این میان خبری بسیار مسرت بخش به مهیار رسید که بازیگر افسانه ای نقش ژنرال کنوبی در سری فیلم های جنگ ستارگان قصد سفر و بازدید به شکرستون را کرده است برای همین مهیار تصمیم گرفت که شغلش را از از برنامه نویس به به برنامه ریز تورهای سیاحتی تغییر دهد. اما قبل از این تصمیم کلان مهیار متوجه مشکل زیرساخت تکنولوژیکی شدیدی در شکرستون شد که حتی گریبانگیر تیم اسنپ نیز شده بود.
اسنپ در این شهر برخلاف سایر شهرها هیچ نقشه ای از آن ندارد و مردم شکرستون صرفا با وارد کردن نام محله های مبدا و مقصد درخواست تاکسی میکنند. فلذا مهیار از بچه های عمران و شهرسازی دانشگاه صنعتی شکرستون درخواست کرد که در سریع ترین زمان ممکن نقشه ای از راه های سطح شهر تهیه کنند تا تاکسی اینترنتی خودش را به بازار شکرستون عرضه کند. در گام بعدی مهیار API شکرستون را بر اساس اطلاعات جمع آوری شده، طراحی کرده است که اطلاعات زیر را بر میگرداند:
- نقاط ضروری برای رسم راه ها برحسب طول و عرض جغرافیایی (بر حسب درجه) که از طریق api/node قابل دسترس است.
- مربع در برگیرنده شکرستون که شامل بیشترین و کمترین، طول و عرض جغرافیایی این شهر می باشد و از طریق `api/bounds` قابل دسترسی است.
- همچنین شیوه اتصال نقاط در `api/way` قابل دریافت است که در قالب آرایه ای از شی های برگردانده می شود.
وسیله نقلی اصلیه شکرستون برای مقابله با اثرات زیست محیطی، زیباسازی شهر و آوردن خنده بر لب مردم شکرستون و جذب توریست های داخلی و خارجی، بر خلاف بسیاری از کلانشهرا که ماشین های لاکچری را ترجیح میدهند، حیوان دوست داشتنی خر می باشد، اما تیم اسنپ با خرها مشکلی اساسی داشت که البتی ناشی از عدم وجود نقشه نیز بود، آن هم این بود که در اکثر مواقع با وجود اینکه خرها مسافر را به مقصد میرساندند اما از هر مسیری که دلشان میخواست حرکت میکردند که نه تنها کوتاه ترین مسیر نبود بلکه طولانی ترین مسیر نیز بود. نکته جالب دیگر شکرستون این است که تمامی راه های موجود در این شهر دوطرفه هستند. به همین جهت مهیار تصمیم گرفته است نام استارتاپش را "خرنپ" بگذارد.
مهیار در ابتدا به اشتباه گمان میکرد پیاده سازی و اجرای الگوریتم های مسیریابی در سمت مرورگر کار درست و عقلانی است اما پس از صحبتهایی مفصل با علی آقا که از دانشجویان ممتاز دانشگاه صنعتی شکرستون می باشند، متوجه شد که کار اشتباهی است و تصمیم گرفت پیشنهاد علی آقا را مبنی بر اینکه مسیریابی در سمت سرور انجام بگیرد را پذیرفت. لکن برای پیدا کردن یک الگوریتم مسیریابی خوب تصمیم گرفت پیش یکی از اساتید پیشگام در حوزه گراف دانشگاه شکرستون یعنی جناب دکتر دیکسترا برود که متاسفانه ایشان به مسافرت رفته بود، به همین جهت او به الگوریتم BFS بسنده کرد و جهت استفاده از آن آدرس `api/route` را به آن اختصاص داد که با فرستادن شناسه مبدا و مقصد در قالب متد `POST`، کوتاه ترین مسیر (یا حداقل از مسیر خرها بسیار کوتاه تر) را در قالب آرایه ای شامل شناسه Node ها را بر میگرداند.
همچنین او از شما خواسته سیستم برای گذاشتن نشان (Marker) روی نقشه نیز برنامه را به نحوی طراحی کنید تا بتواند مبدا و مقاصد مورد نظر را به راحتی تعیین نماید که در جلوتر به صورت مفصل آن را توضیح خواهد داد.
از آنجایی که ژنرال کنوبی راس ساعت 6:05PM به شکرستون میرسد مهیار از شما می خواهد تا این زمان برنامه را تکیمل کنید. هرچند طبق گفته های مهیار اسنپ قول داده است که اگر این برنامه در راس زمان مقرر تکیمل بشود، استارتاپ خرنپ را با قیمت خوبی بخرد و شما را نیز به عنوان یک توسعه دهند قابل و توانا استخدام نماید.
ازآنجایی که مهیار درگیر تدارک دیدن خوش آمد گویی ژنرال کنوبی است در گام اول از شما خواسته است که اطلاعات دریافتی از API را در قالب یک نقشه گرافیکی با استفاده از کتابخانه react طراحی نمایید. (قابل به ذکر است که مهیار چند کامپوننت از قبل آماده شده برای راحت تر شدن استایل دهی پروژه و همچنین تسریع در روند توسعه آن تدارک دیده است که جزییات هریک را در قالب یک داکیومنت در اختیار شما می گذارد).
همچنین مهیار با توجه به ضیق وقت، سلیب را که از تیم لیدهای بسیار خوب در توسعه نرم افزار، دادن نقشه راه و روند طراحی نرم افزار است را استخدام کرده که نرم افزار نهایی علاوه بر دیپلوی شدن در وقت موعد، maintainable و قابل توسعه بیشتر در آینده نه چندان دور باشد و هم چنین روند توسعه درست و اصولی را برای شما مشخص نماید.
# نکات سیستم داوری
برای ارزیابی درست تمارین شما رعایت موارد زیر الزامی است:
- برای دریافت مکان نشانگر mouse حتما از clientX و clientY استفاده کنید.
- هوک useMap به طور مستقیم ارزیابی نمی شود و فقط جهت سهولت در تکمیل تمرین می باشد
- کامپوننت MapWidget به طور مستقیم ارزیابی نمی شود و فقط جهت سهولت در تکمیل تمرین می باشد.
# موارد خواسته شده
<details class="yellow">
<summary>
تابع ``utils/calcDistance.js``
</summary>
در این فایل یک تابع هم نام با فایل وجود دارد که وظیفه تکمیل آن نیز بر عهده شما می باشد.به عنوان ورودی دو نقطه را که هر نقطه شامل طول و عرض جغرافیایی هستند را دریافت می کند و فاصله آن ها را محاسبه کرده و بر میگرداند. برای محاسبه فواصل درون شهری با دقت نسبتا خوبی میتوان از فرمول هاورسین (Haversian) استفاده نمود، که بیان ریاضی این به شرح زیر است.
https://quera.ir/contest/assignments/36266/problems/125390
$$ R = 6371000 $$
$$ \phi = latitude\hspace{5mm}\lambda = longitude $$
$$ \Delta\phi = \phi_2 - \phi_1 $$
$$ \Delta\lambda = \lambda_2 - \lambda_1 $$
$$ a = sin^2(\Delta\phi/2) + cos(\phi_1).cos(\phi_2).sin^2(\Delta\lambda/2) $$
$$ c = 2 . atan2(\sqrt{a}.\sqrt{1- a}) $$
$$ d = R.c $$
که R بیانگر شعاع زمین برحسب متر و d بیانگر فاصله بین دو نقطه برحسب متر می باشد.
نکته: دقت شود که atan2 مفهوم کاملا متفاوتی نسب به تانژات معکوس دارد( فی الواقع بیان میزان اختلاف درجه نقطه ای دلخواه بر روی صفحه با محور افقی می باشد)
</details>
<details class="yellow">
<summary>
تابع ``utils/calcPositionCss.js``
</summary>
در این فایل یک تابع هم نام با فایل وجود دارد که وظیفه تکمیل آن نیز بر عهده شما می باشد.به عنوان ورودی node, bound را میگیرد و مکان node را برحسب درصد نسبت به یکی left/right در راستای محور افقی و top/bottom در راستای محور عمودی بیان میکند.(دقت کنید که شکل نهایی خروجی باید مطابق گیف باشد و دارای هیچ چرخش اضافه ای نباشد)
راهنمایی I : اگر بخواهیم مولفه های موقعیت جغرافییایی را در قالب دستگاه کارتزین تصور کنیم، عرض جغرافیایی (longitude) معادل x و طول جفرافیایی (latitude) معادل y می شود.
راهنمایی II : راه های زیادی برای این نگاشت وجود دارد که بر حسب فرمول های ریاضی پیچیده با در نظر گرفتن کره ای بودن زمین می باشد، اما چون وقت محدود است مهیار بهبود این امر را به آینده موکول کرده و از دوست ریاضیدانش جان فون نیومان درخواست کمک کرده است که در فاز بعدی بهبود این ضعف نیز بر طرف شود، اما علی الحساب جان فون نیومان پیشنهاد کرده است که برای تخمین مکان نقطه بر روی صفحه، این امر محاسبه شود که این نقطه چه کسری از اضلاع مستطیل در برگیرنده شکرستون می باشد، برای مثال:
![desc](https://quera.ir/qbox/view/9lGpeeY3OU/dist.png)
</details>
<details class="green">
<summary>
فایل `api/index.js`
</summary>
در این فایل شما باید 4 تابع را به نحوی پیاده سازی کنید که اطلاعات هر مسیر را از سرور دریافت کند
- تابع :`getBounds` برای دریافت اطلاعات bounds شهر شکرستون که درخواستی از نوع GET به آدرس مورد نظر ارسال میکند. نمونه داده دریافتی به شرح زیر است:
```json
{
"minlat": "123.987",
"minlon": "5642.12354",
"maxlat": "123.12321",
"maxlon": "1245.456"
}
```
- تابع `getNodes`: برای دریافت موقعیت های جغرافیایی شهر شکرستون که درخواستی از نوع GET به آدرس مورد نظر ارسال میکند. نمونه داده دریافتی به شرح زیر است:
```json
[
{
"id": "942401067",
"lat": "33.5031685",
"lon": "51.9268632"
},
{
"id": "942401068",
"lat": "33.5101294",
"lon": "51.9202060"
}
]
```
- تابع `getWays`: برای دریافت اطلاعات مسیرهای شهر شکرستون که درخواستی از نوع GET به آدرس مورد نظر ارسال میکند. نمونه داده دریافتی به شرح زیر است:
```json
[
{
"id": "80818771",
"nd": [
"942401300",
"942401130",
"5202757684",
"3539769753",
"3539769746",
"5202757588",
"5202757591",
"5202757579",
"5202704676",
"942401196",
"942401359",
"2989992895"
]
}
]
```
- تابع :`getPath` که با فرستادن شناسه(id) مبدا و مقصد در قالب یک درخواست از نوع POST اطلاعات مسیر را دریافت می کند.
```json
// REQUEST POST
{
"src": "5202757608", // SOURCE NODE ID
"dst": "5202757524" // DESTINATION NODE ID
}
// RESPONSE
{
"path": [
"5202757608",
"5202757609",
"5202757610",
"5202757611",
"5202757630",
"5202757629",
"5202757541",
"5202757540",
"5202757539",
"5202757538",
"5202757550",
"5202757537",
"5202757536",
"5202757542",
"5202757535",
"5202757547",
"5202757534",
"942401095",
"5202757522",
"942401261",
"942401291",
"5202757524"
]
}
```
</details>
<details class="blue">
<summary>
هوک `useAPI`
</summary>
هدف از این هوک استفاده از توابع ذکر شده و ذخیره مقادیر دریافتی در سه state مجزا با نام های nodes, ways, bounds می باشد، در نهایت این هوک تنها این مقادیر این سه state را بر میگرداند.
</details>
<details class="blue">
<summary>
هوک `useMarker`
</summary>
هدف از طراحی این هوک به شرح زیر است:
- گذاشتن نشان روی نقشه
- محاسبه نزدیک ترین node به نشان گذاشته شده
- نمایش دادن نشان ها بر روی صفحه
این هوک به عنوان ورودی یک reference و اطلاعات نقشه را دریافت می کند و دارای دو state تحت عنوانه:
- `marker` برای ذخیره مکان نشان ها می باشد
- `Cords` برای ذخیره نزدیک ترین node به نشان وارد شده
و به عنوان خروجی توابع و استیت زیر را بر میگرداند:
- `addMarker` که بعنوان ورودی شی event را دریافت کرده و یک marker, cords جدید اضافه می کند
- `deleteMarker` هیچ ورودی نمی گیرد و صرفا state ها را خالی میکند
- `renderMarker` نشان ها را با استفاده از کامپوننت`Marker.jsx` در قالب یک لیست جهت نمایش بر میگرداند، کامپوننت مارکر به عنوان Attribute دو ورودی x, y را میگیرد که بیانگر موفعیت آن در صفحه متناسبش می باشد.
- `cords` که شامل نزدیک ترین Node به هر نشان است.
- نکته: محدودیتی در تعداد نشان ها وجود ندارد.
</details>
<details class="blue">
<summary>
هوک `useNavigator `
</summary>
این هوک به عنوان ورودی اطلاعات نقشه و اطلاعات جغرافیایی نشان ها را دریافت میکند و بعنوان خروجی تالعی تحت عنوان `renderWays` را بر میگرداند که وظیفه اصلی آن نمایش راه هاست. سپس با استفاده از `API` طراحی شده در بخش قبل و با استفاده از نشان های دریافتی مسیر متناسب گذرنده میان نشان ها را دریافت میکند. برای نمایش مسیر شما باید در صورتی که راه در در حال رسم بخشی از مسیر پیش بینی شده بود پراپرتی مناسب را به آن پاس دهید.
همچنین تابع دیگری تحت عنوان `getDistance` نیز برمیگرداند که مسافت طی شده را بر حسب متر با استفاده از تابع `calcDistance` محاسبه کرده و حاصل آن را بر میگرداند.
</details>
<details class="blue">
<summary>
هوک `useMap`
</summary>
هدف از طراحی این هوک استفاده از سه هوک طراحی شده قبلی میباشد و به عنوان ورودی یک `reference` دریافت میکند و توابع زیر را به عنوان خروجی بر میگرداند.
- تابعی تحت عنوان `renderMap` برای رندر کردن تمام المان ها
- تابع اضافه کردن نشان بر روی نقشه
- تابع حذف نشان های روی نقشه
</details>
</details>
<details class="red">
<summary>
کامپوننت `<Distance />`
</summary>
هدف از طراحی این کامپوننت نشان دادن مسافت پیموده شده با دقت دو رقم اعشار، نشان ها میباشد که باید درون یک تگ ```span``` به صورت زیر نشان داده شود:
```
distance = 1.25 km
```
در صورتی که فاصله قابل تبدیل به km بود باید به صورت km ای نشان داده شود (یعنی اگر بزرگتر از 1000 متر بود) در غیر این صورت به صورت همان متر نشان داده شود:
```
distance = 924.56 m
```
که مقدار مسافت پیموده شده برحسب متر در قالب prop ای تحت عنوان distance پاس داده میشود:
```jsx
<Distance distance={123.56} />
```
</details>
</details>
<details class="red">
<summary>
کامپوننت `<MapWidget />`
</summary>
این کامپوننت دو پراپ تحت عنوان های deleteMarkers که یک تابع است که عمل پاک کردن مارکر ها را انجام میدهد و دیگری فاصله بر حسب متر یا همان distance می باشد.
حال شما باید این کامپوننت را به نحوی تکمیل کنید که پراپها به نحو درست به کامپوننت های ```<Distance />``` و ```<ClearButton />``` پاس داده شوند و هردوی آنها درون ```<Row> </Row>``` قرار بگیرند
</details>
</details>
<details class="red">
<summary>
کامپوننت `<Map />`
</summary>
در گام آخر در این کامپوننت شما باید با استفاده از هوک ```useMap``` طراحی شده نقشه را در درون ```<Relative/>``` با کلاس ```map``` نمایش دهید و همچنین در صورتی که بر روی آن کلیک شد باید یک نشان به مجموعه نشان ها اضافه شود.
و یک کامپوننت دیگر یعنی همان ```<MapWidget />``` با پراپ های مطلوب نمایش داده شود.
و همچنین هردوی این کامپوننتها باید درون تگ ```<div>``` قرار بگیرند
</details>
# موارد پیاده شده
</details>
<details class="blue">
<summary>
کامپوننت `<Marker/>`
</summary>
به عنوان پراپهای ورودی متغییرهای x و y را که بیانگر فاصله از سمت چپ و بالا می باشند دریافت میکند، و یک المان به صورت absolute به عنوان marker را نمایش میدهد
</details>
</details>
<details class="green">
<summary>
کامپوننت `<Row/>`
</summary>
یک ردیف ایجاد می کنید و هیچ ورودی دریافت نمی کند
</details>
</details>
<details class="green">
<summary>
کامپوننت `<ClearButton />`
</summary>
به عنوان ورودی یک تابع onClick میگیرد
</details>
</details>
<details class="red">
<summary>
کامپوننت `<Relative/>`
</summary>
یک المان با استایل relative نمایش میدهد
</details>
</details>
<details class="red">
<summary>
کامپوننت `<Way />`
</summary>
به عنوان ورودی شناسه src و dst را دریافت کرده و متغیر bool تحت عنوان isPath نیز دریافت میکند که بیانگر مسیر بودن یا نبودن می باشد
</details>
</details>
<details class="yellow">
<summary>
کامپوننت `<Node />`
</summary>
به عنوان ورودی طول و عرض جفرافیایی را در قالب lat و lon دریافت کرده علاوه بر آن مربع در برگیرنده را تحت عنوان bounds دریافت کرده و همچنین شناسه موقعیت جغرافیایی را نیز دریافت میکند.
</details>