نظرسنجی کوئرا


ظاهر کلی برنامه بدین صورت است:

ظاهر برنامه

پروژه اولیه🔗

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

ساختار فایل‌های پروژه
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
Plain text

جزئیات🔗

کوئرا قصد دارد در سال 1400 از برنامه نویسان ایرانی در مورد بهترین های برنامه نویسی مانند بهترین فریمورک برای توسعه وب و... نظرسنجی کند. برای مشارکت بیشتر، تصمیم بر این شد فرم نظرسنجی در بستر وب و با ایموجی ساخته بشه. نادر قسمتی از پروژه رو برای کوئرا انجام داد اما او رفیق نیمه راه بود و قبل کامل کردن پروژه فرار کرد. حال ما از شما برای تکمیل این پروژه کمک میخواهیم.

توضیحات🔗

  • اطلاعات ایموجی ها

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

{
  title: عنوان ایموجی,
  src: سورس عکس ایموجی,
  isSelected: انتخاب شدن ایموجی در چک باکس,
  description: توضیحات ایموجی
}
Plain text
  • کامپوننت ShowEmoji

از این کامپوننت برای نمایش ایموجی ها در قسمت description و preview استفاده کنید. این کامپوننت سه پراپس به شرح زیر میگیرد:

  • پراپس src : سورس ایموجی مورد نظر میباشد.

  • پراپس viewStyle : یک استرینگ با مقادیر "description" یا "preview" که استایل مناسب هر قسمت را به ایموجی میدهد.

  • پراپس name : عنوان ایموجی را میگیرد که برابر alt ایموجی قرار میگیرد.

مواردی که باید پیاده سازی شوند🔗

کامپوننت DescriptionItem

این کامپوننت باید به گونه ای پیاده سازی شود که در صورت انتخاب شدن هر ایموجی، قسمتی شامل یک input و ایموجی مورد نظر، در قسمت description، مانند تصویر ساخته شود.

  • این کامپوننت دو پراپس با عنوان های emojis و setEmojis میگیرد که مقادیر state ایموجی هاست.

  • برای هر ایموجی انتخاب شده، باید یک label و یک input ایجاد شود.

    • لیبل باید ویژگی htmlFor برابر با عنوان ایموجی را داشته باشد.
    • برای نمایش ایموجی درون label از کامپوننت ShowEmoji استفاده کنید.
    • اینپوت باید id برابر با عنوان ایموجی داشته باشد.
  • در صورت نوشته شدن درون input باید state آپدیت شده و مقدار وارد شده در آبجکت همان ایموجی ست شود.

  • در صورت غیر فعال شدن ایموجی قسمت description مربوط به آن ایموجی باید از بین برود.

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

  • این کامپوننت یک پراپس با عنوان ٍemojis میگیرد که اطلاعات ایموجی ها درون آرایه ای از آبجکت هاست.

  • برای نمایش ایموجی ها از کامپوننت ShowEmoji استفاده کنید.

  • برای نمایش توضیحات از تگ div استفاده کنید.

نکات🔗

شما تنها مجاز به اعمال تغییرات در فایل های DescriptionItem.js و ShowPreviewEmoji.jsهستید.

برای ارسال پاسخ کل پروژه را zip کرده و ارسال کنید. دقت کنید که پوشه‌ی node_modules در فایل ارسالی نباشد.

سلامت سرور


ظاهر کلی برنامه بدین صورت است:

ظاهر برنامه

پروژه اولیه🔗

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

ساختار پروژه
retry
├── public
│   ├── favicon.ico
│   └── index.html
├── server
│   └── server.js
├── src
│   ├── __tests__
│   │   └── sample.test.js
│   ├── App.js
│   ├── index.css
│   └── index.js
├── package-lock.json
└── package.json
Plain text
راه‌اندازی پروژه

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

  • ابتدا پروژه‌ی اولیه را دانلود و از حالت فشرده خارج کنید.
  • در پوشه‌ی retry ، دستور npm install را برای نصب نیازمندی‌ها اجرا کنید.
  • در همین پوشه، دستور npm start را برای راه‌اندازی پروژه اجرا کنید.
  • پس از انجام موفق این مراحل، با مراجعه به آدرس http://localhost:3000/ می‌توانید نتیجه را ببینید.
راه‌اندازی سرور
  • در پوشه‌ی retry ، دستور npm install را برای نصب نیازمندی‌ها اجرا کنید.
  • در همین پوشه، دستور npm run server را برای راه‌اندازی سرور پروژه اجرا کنید.

جزئیات🔗

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

مواردی که باید در این سوال به آنها دقت کنید:

  • بلافاصله بعد از لود شدن صفحه، ارسال درخواست‌ها شروع میشود و اولین درخواست فرستاده میشود. بعد از آن درخواست‌ها با تاخیر فرستاده میشوند. تاخیر بین درخواست‌ها از firstRetryDelay (که کامپوننت به عنوان پراپرتی میگیرد) شروع میشود و هر بار به اندازه همان firstRetryDelay به آن اضافه میشود.
  • آدرس که درخواست‌ها به آن ارسال میشود به عنوان پراپرتی با نام url دریافت میشود.‌ (برای اینکه این آدرس کار کند، باید سرور طبق توضیحات بالا راه‌اندازی شود)
  • اگر درخواستی موفقیت آمیز بود (status برابر ۲۰۰ باشد)، درخواست دیگری بعد از تاخیر ارسال میشود.
  • اگر درخواستی ناموفق بود‌ (status برابر ۵۰۰ باشد)، نتیجه نمایش داده میشود. فرمت نتیجه بعد از ناموفق بودن درخواست: (که <attemptCount> همان تعداد تلاش‌ها تا این درخواست با شمردن این درخواست است)
Failed after <attemptCount> attempts.
Plain text
  • ماکسیمم تعداد درخواست‌ها به تعداد maxAttempts که از پراپرتی گرفته میشود. اگر بعد از ماکسیمم تعداد درخواست، همه‌ی تلاش‌ها موفقیت آمیز بود، نتیجه نمایش داده میشود. فرمت نتیجه بعد از موفق بودن همه‌ی درخواست‌ها:
Success after <attemptCount> attempts.
Plain text
  • المان #message برای نشان دادن پیشرفت درخواست‌‌ها است. بعد از اتمام هردرخواست پیامی با فرمت زیر نمایش داده میشود:
Attempt <previousAttempt> done. Retrying in <nextDelay> milliseconds...
Plain text

و فقط موقع اولین درخواست پیامی که نوشته میشود:

First Attempt...
Plain text

نکات🔗

  • همه‌ی درخواست‌ها از نوع GET هستند و باید با fetch انجام شوند.
  • شما تنها مجاز به اعمال تغییرات در فایل src/App.js هستید.
  • برای ارسال پاسخ میتوانید فقط فایل App.js را بدون zip کردن ارسال کنید یا کل پروژه را zip کرده و ارسال کنید. دقت کنید که پوشه‌ی node_modules در فایل ارسالی نباشد.

صرافی شمس‌الله (۲)


پروژه اولیه🔗

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

ساختار فایل‌های این پروژه به این صورت است
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
Plain text
راه‌اندازی پروژه

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

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

جزئیات🔗

ظاهر کلی برنامه بدین صورت است:

ظاهر برنامه

در مسابقه فرانت‌اند قبل با شمس‌الله آشنا شدید و به او کمک کردید که یک نمودار قیمت برای ارز دروغین خود بسازد و سر مردم را کلاه بگذارد (شریک جرم شدید!! :)) ). شمس‌الله با این کار پول خوبی به جیب زد و حالا قرار است صرافی خود را بهبود ببخشد. برای این کار قرار است شمس‌الله به صرافی خود یک جدول سفارشات (orderbook) اضافه کند تا مردم بیشتری به او و صرافی‌اش اعتماد کنند. مثل گذشته شمس‌الله از شما می‌خواهد که در پیاده‌سازی فرانت‌اند این قسمت نیز به او کمک کنید.

جدول سفارشات (orderbook):🔗

یکی از روش‌هایی که معامله‌گران برای پیدا کردن نقطه ورود و خروج مناسب استفاده می‌کنند، خواندن جدول سفارشات است. در این جدول سفارش‌های انجام نشده در یک بازار مشخص می‌شود و مشخص می‌شود که در یک قیمت مشخص حجم سفارش‌ها چقدر است. برای مثال یک فرد در قیمت ۱۰۰ دلار :))) می‌خواهد یک بیت‌کوین بخرد. فرد دیگر در همین مقدار قیمت می‌خواهد دوتا بیت‌کوین بخرد. پس در قیمت ۱۰۰ دلار حجم سفارش‌ها ۱ + ۲ = ۳ است. یعنی برای رد شدن از این قیمت باید حداقل ۳ بیت‌کوین خریداری شود. (توسط فرد یا افراد دیگر فروخته شود) معامله‌گران از این روش متوجه می‌شوند که حجم سفارش‌ها در چه بازه‌ قیمتی زیاد است و از آن برای پیاده کردن نقطه ورود و خروج مناسب استفاده می‌کنند. این جدول از دو قسمت اصلی تشکیل شده است. یک قسمت برای سفارش‌های خرید و یک قسمت برای سفارش‌های فروش است. هر دو قسمت براساس بهترین قیمت مرتب می‌شوند. بهترین قیمت در قسمت خرید، بیشترین قیمت است و در قسمت فروش کمترین قیمت است. (منطقی به‌نظر می‌رسه :)) )

اجزای جدول سفارشات (orderbook):🔗

ستون‌های هر قسمت از این جدول (قسمت خرید و فروش) عبارت است از: قیمت و مقدار و مقدار کل. قیمت مشخص‌کننده قیمت در آن سطر است. مقدار مشخص‌کننده مقدار عرضه شده از آن ارز در آن قیمت است. مقدار کل برابر است حجم عرضه شده از اولین سفارش (بهترین سفارش) تا آن سفارش بعلاوه خودش. برای مثال در تصویر زیر در قیمت ۲۰۰ ریال ۳۷ تا ارز شمس‌الله توسط افرادی قرار است خریداری شود. در این قیمت چون بهترین قیمت است (در قسمت خرید بهترین قیمت، بیشترین قیمت است) حجم سفارشات قبل آن ۰ است. در قیمت ۱۹۹ ریال مقدار برابر ۳۲ است و حجم سفارشات قبل این قیمت برابر ۳۷ است. پس مقدار کل برابر ۳۲ + ۳۷ = ۶۹ می‌شود. به همین شکل برای باقی قیمت‌ها و قسمت فروش اعداد محاسبه می‌شوند. در قسمت فروش بهترین قیمت کمترین قیمت است. رنگ پشت‌زمینه نشان‌دهنده درصد مقدار کل در آن قیمت به بیشترین مقدار کل در هر دو قسمت جدول سفاراشات، که با توجه به تجمعی بدون این شاخص،‌ بیشترین مقدار کل برابر است با بدترین قیمت (آخرین قیمت) هر قسمت (خرید و فروش).

ظاهر برنامه

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

وظیفه توسعه‌دهنده فرانت‌اند:🔗

در این پروژه شما باید با استفاده از دیتای داده شده، جدول سفارشات این ارز را بسازید.

ساختار داده‌ به‌شکل زیر است:

{
  "quantity": number,
  "price": number,
  "type": "sell" | "buy"
}[]
JSON

که در آن price نشان‌دهنده قیمت، quantity نشان‌دهنده تعداد سفارشات در آن قیمت و type نشان‌دهنده نوع سفارش است که می‌تواند خرید (buy) یا فروش (sell) باشد.

این دیتا به کامپوننت App.jsx داده می‌شود.

مواردی که باید در این سوال رعایت کنید:🔗

  • شما باید ابتدا ساختار مورد نظر را بسازید و در قسمت‌های مشخص شده در پروژه اولیه لیست سفارش‌های خرید و فروش را با استفاده از کامپوننت ‍OrderbookListItem نمایش دهید.
  • این کامپوننت مقادیر زیر را به عنوان props دریافت می‌کند و یک سطر از یک طرف جدول سفارشات را می‌سازد. شکل پراپس‌های دریافتی کامپوننت عبارت است از:
  • index:‌ نشان‌دهنده ایندکس آرایه است. دقت کنید این ایندکس باید برابر ایندکس آرایه مرتب شده براساس بهترین قیمت در هر قسمت خرید و فروش باشد.
  • type:‌ این مقدار یا باید برابر با buy یا برابر با sell باشید.
  • price:‌ نشان‌دهنده قیمت آن سفارش است.
  • amount:‌ نشان‌دهنده حجم سفارشات در آن است. دقت کنید فقط مقدار سفارش‌های آن قیمت.
  • total:‌ نشان‌دهنده حجم کل سفارشات تا آن قیمت است. دقت کنید مقدار سفارش‌های آن قیمت بعلاوه حجم بقیه سفارشات تا آن قیمت. (براساس بهترین سفارش)
  • bgWidth:‌ نشان‌دهنده درصد رنگ پشت‌زمینه (درصد حجم سفارشات آن قیمت به بیشتر حجم) است.

راهنمایی: در هنگام محاسبه این عدد دقت کنید که شما باید مقدار کل در ردیف را به بیشتر‌ین مقدار کل (مقدار کل ردیف‌ آخر قسمت خرید و فروش) حساب کنید. (براساس درصد) برای مثال اگر مقدار کل سفارشات خرید برابر ۱۰۰۰ و سفارشات فروش برابر ۱۵۰۰ باشد. شما باید مقدار کل هر ردیف تقسیم برای ۱۵۰۰ ضبدر ۱۰۰ کنید. برای مثال بالا این شاخص برای اولین سفارش خرید برابر (۱۰۰ * ۳۷ / ۱۵۰۰) است و شما باید برای کامپوننت مقدار ۲.۴۶% را ارسال کنید. (دقت برابر دو رقم اعشار باشد)

نکات🔗

  • برای ارسال پاسخ کل پروژه را zip کرده و ارسال کنید. دقت کنید که پوشه‌ی node_modules در فایل ارسالی نباشد.

اسنپ در شکرستون


پروژه اولیه🔗

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

ساختار فایل‌های این پروژه به این صورت است

snapp-shekarstoon
├── package.json
├── package-lock.json
├── public
│   └── index.html
├── server
│   ├── data
│   │   └── data.json
│   ├── index.js
│   ├── utils
│   │   └── router.js
│   └── views
│       └── index.html
└── src
    ├── API
    │   └── index.js
    ├── App.js
    ├── Components
    │   ├── Map
    │   │   ├── Map.jsx
    │   │   ├── Relative.jsx
    │   │   └── Way.jsx
    │   ├── MapWidget
    │   │   ├── ClearButton.jsx
    │   │   ├── Distance.jsx
    │   │   ├── MapWidget.jsx
    │   │   └── Row.jsx
    │   ├── Marker.jsx
    │   ├── Node
    │   │   ├── Absolute.jsx
    │   │   └── Node.jsx
    │   └── UI
    │       └── Title.jsx
    ├── hooks
    │   ├── useAPI.jsx
    │   ├── useMap.jsx
    │   ├── useMarker.jsx
    │   └── useNavigator.jsx
    ├── index.js
    ├── styles
    │   ├── absolute.scss
    │   ├── btn.scss
    │   ├── marker.scss
    │   ├── relative.scss
    │   ├── row.scss
    │   └── title.scss
    └── utils
        ├── calcDistance.js
        └── calcPositionCSS.js
Plain text
راه اندازی پروژه
  • ابتدا پروژه‌ی اولیه را دانلود و از حالت فشرده خارج کنید.

  • سپس با اجرای دستور npm i پکیج های مورد نیاز را نصب نمایید

  • با اجرای دستور node server/index.js سرور را اجرا نمایید.

  • با اجرای دستور npm start پروژه را اجرا نمایید

جزئیات🔗

sample_gif

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

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

  • نقاط ضروری برای رسم راه ها برحسب طول و عرض جغرافیایی (بر حسب درجه) که از طریق api/node قابل دسترس است.

  • مربع در برگیرنده شکرستون که شامل بیشترین و کمترین، طول و عرض جغرافیایی این شهر می باشد و از طریق api/bounds قابل دسترسی است.

  • همچنین شیوه اتصال نقاط در api/way قابل دریافت است که در قالب آرایه ای از شی های برگردانده می شود.

وسیله نقلی اصلیه شکرستون برای مقابله با اثرات زیست محیطی، زیباسازی شهر و آوردن خنده بر لب مردم شکرستون و جذب توریست های داخلی و خارجی، بر خلاف بسیاری از کلانشهرا که ماشین های لاکچری را ترجیح میدهند، حیوان دوست داشتنی خر می باشد، اما تیم اسنپ با خرها مشکلی اساسی داشت که البتی ناشی از عدم وجود نقشه نیز بود، آن هم این بود که در اکثر مواقع با وجود اینکه خرها مسافر را به مقصد میرساندند اما از هر مسیری که دلشان میخواست حرکت میکردند که نه تنها کوتاه ترین مسیر نبود بلکه طولانی ترین مسیر نیز بود. نکته جالب دیگر شکرستون این است که تمامی راه های موجود در این شهر دوطرفه هستند. به همین جهت مهیار تصمیم گرفته است نام استارتاپش را "خرنپ" بگذارد.

مهیار در ابتدا به اشتباه گمان میکرد پیاده سازی و اجرای الگوریتم های مسیریابی در سمت مرورگر کار درست و عقلانی است اما پس از صحبتهایی مفصل با علی آقا که از دانشجویان ممتاز دانشگاه صنعتی شکرستون می باشند، متوجه شد که کار اشتباهی است و تصمیم گرفت پیشنهاد علی آقا را مبنی بر اینکه مسیریابی در سمت سرور انجام بگیرد را پذیرفت. لکن برای پیدا کردن یک الگوریتم مسیریابی خوب تصمیم گرفت پیش یکی از اساتید پیشگام در حوزه گراف دانشگاه شکرستون یعنی جناب دکتر دیکسترا برود که متاسفانه ایشان به مسافرت رفته بود، به همین جهت او به الگوریتم BFS بسنده کرد و جهت استفاده از آن آدرس api/route را به آن اختصاص داد که با فرستادن شناسه مبدا و مقصد در قالب متد POST، کوتاه ترین مسیر (یا حداقل از مسیر خرها بسیار کوتاه تر) را در قالب آرایه ای شامل شناسه Node ها را بر میگرداند.

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

از آنجایی که ژنرال کنوبی راس ساعت 6:05PM به شکرستون میرسد مهیار از شما می خواهد تا این زمان برنامه را تکیمل کنید. هرچند طبق گفته های مهیار اسنپ قول داده است که اگر این برنامه در راس زمان مقرر تکیمل بشود، استارتاپ خرنپ را با قیمت خوبی بخرد و شما را نیز به عنوان یک توسعه دهند قابل و توانا استخدام نماید.

ازآنجایی که مهیار درگیر تدارک دیدن خوش آمد گویی ژنرال کنوبی است در گام اول از شما خواسته است که اطلاعات دریافتی از API را در قالب یک نقشه گرافیکی با استفاده از کتابخانه react طراحی نمایید. (قابل به ذکر است که مهیار چند کامپوننت از قبل آماده شده برای راحت تر شدن استایل دهی پروژه و همچنین تسریع در روند توسعه آن تدارک دیده است که جزییات هریک را در قالب یک داکیومنت در اختیار شما می گذارد).

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

نکات سیستم داوری🔗

برای ارزیابی درست تمارین شما رعایت موارد زیر الزامی است:

  • برای دریافت مکان نشانگر mouse حتما از clientX و clientY استفاده کنید.
  • هوک useMap به طور مستقیم ارزیابی نمی شود و فقط جهت سهولت در تکمیل تمرین می باشد
  • کامپوننت MapWidget به طور مستقیم ارزیابی نمی شود و فقط جهت سهولت در تکمیل تمرین می باشد.

موارد خواسته شده🔗

تابع utils/calcDistance.js

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

https://quera.ir/contest/assignments/36266/problems/125390 R=6371000 R = 6371000

ϕ=latitudeλ=longitude \phi = latitude\hspace{5mm}\lambda = longitude

Δϕ=ϕ2ϕ1 \Delta\phi = \phi_2 - \phi_1

Δλ=λ2λ1 \Delta\lambda = \lambda_2 - \lambda_1

a=sin2(Δϕ/2)+cos(ϕ1).cos(ϕ2).sin2(Δλ/2) a = sin^2(\Delta\phi/2) + cos(\phi_1).cos(\phi_2).sin^2(\Delta\lambda/2)

c=2.atan2(a.1a) c = 2 . atan2(\sqrt{a}.\sqrt{1- a})

d=R.c d = R.c

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

نکته: دقت شود که atan2 مفهوم کاملا متفاوتی نسب به تانژات معکوس دارد( فی الواقع بیان میزان اختلاف درجه نقطه ای دلخواه بر روی صفحه با محور افقی می باشد)

تابع utils/calcPositionCss.js

در این فایل یک تابع هم نام با فایل وجود دارد که وظیفه تکمیل آن نیز بر عهده شما می باشد.به عنوان ورودی node, bound را میگیرد و مکان node را برحسب درصد نسبت به یکی left/right در راستای محور افقی و top/bottom در راستای محور عمودی بیان میکند.(دقت کنید که شکل نهایی خروجی باید مطابق گیف باشد و دارای هیچ چرخش اضافه ای نباشد)

راهنمایی I : اگر بخواهیم مولفه های موقعیت جغرافییایی را در قالب دستگاه کارتزین تصور کنیم، عرض جغرافیایی (longitude) معادل x و طول جفرافیایی (latitude) معادل y می شود.

راهنمایی II : راه های زیادی برای این نگاشت وجود دارد که بر حسب فرمول های ریاضی پیچیده با در نظر گرفتن کره ای بودن زمین می باشد، اما چون وقت محدود است مهیار بهبود این امر را به آینده موکول کرده و از دوست ریاضیدانش جان فون نیومان درخواست کمک کرده است که در فاز بعدی بهبود این ضعف نیز بر طرف شود، اما علی الحساب جان فون نیومان پیشنهاد کرده است که برای تخمین مکان نقطه بر روی صفحه، این امر محاسبه شود که این نقطه چه کسری از اضلاع مستطیل در برگیرنده شکرستون می باشد، برای مثال:

desc

فایل api/index.js

در این فایل شما باید 4 تابع را به نحوی پیاده سازی کنید که اطلاعات هر مسیر را از سرور دریافت کند

  • تابع :getBounds برای دریافت اطلاعات bounds شهر شکرستون که درخواستی از نوع GET به آدرس مورد نظر ارسال میکند. نمونه داده دریافتی به شرح زیر است:
{
    "minlat": "123.987",
    "minlon": "5642.12354",
    "maxlat": "123.12321",
    "maxlon": "1245.456"
}
JSON
  • تابع getNodes: برای دریافت موقعیت های جغرافیایی شهر شکرستون که درخواستی از نوع GET به آدرس مورد نظر ارسال میکند. نمونه داده دریافتی به شرح زیر است:
[
    {
        "id": "942401067",
        "lat": "33.5031685",
        "lon": "51.9268632"
    },
    {
        "id": "942401068",
        "lat": "33.5101294",
        "lon": "51.9202060"
    }
]
JSON
  • تابع getWays: برای دریافت اطلاعات مسیرهای شهر شکرستون که درخواستی از نوع GET به آدرس مورد نظر ارسال میکند. نمونه داده دریافتی به شرح زیر است:
[
    {
        "id": "80818771",
        "nd": [
            "942401300",
            "942401130",
            "5202757684",
            "3539769753",
            "3539769746",
            "5202757588",
            "5202757591",
            "5202757579",
            "5202704676",
            "942401196",
            "942401359",
            "2989992895"
        ]
    }
]
JSON
  • تابع :getPath که با فرستادن شناسه(id) مبدا و مقصد در قالب یک درخواست از نوع POST اطلاعات مسیر را دریافت می کند.

// 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"
    ]
}
JSON
هوک useAPI

هدف از این هوک استفاده از توابع ذکر شده و ذخیره مقادیر دریافتی در سه state مجزا با نام های nodes, ways, bounds می باشد، در نهایت این هوک تنها این مقادیر این سه state را بر میگرداند.

هوک useMarker

هدف از طراحی این هوک به شرح زیر است:

  • گذاشتن نشان روی نقشه

  • محاسبه نزدیک ترین node به نشان گذاشته شده

  • نمایش دادن نشان ها بر روی صفحه

    این هوک به عنوان ورودی یک reference و اطلاعات نقشه را دریافت می کند و دارای دو state تحت عنوانه:

  • marker برای ذخیره مکان نشان ها می باشد

  • Cords برای ذخیره نزدیک ترین node به نشان وارد شده

و به عنوان خروجی توابع و استیت زیر را بر میگرداند:

  • addMarker که بعنوان ورودی شی event را دریافت کرده و یک marker, cords جدید اضافه می کند

  • deleteMarker هیچ ورودی نمی گیرد و صرفا state ها را خالی میکند

  • renderMarker نشان ها را با استفاده از کامپوننتMarker.jsx در قالب یک لیست جهت نمایش بر میگرداند، کامپوننت مارکر به عنوان Attribute دو ورودی x, y را میگیرد که بیانگر موفعیت آن در صفحه متناسبش می باشد.

  • cords که شامل نزدیک ترین Node به هر نشان است.

  • نکته: محدودیتی در تعداد نشان ها وجود ندارد.

هوک useNavigator

این هوک به عنوان ورودی اطلاعات نقشه و اطلاعات جغرافیایی نشان ها را دریافت میکند و بعنوان خروجی تالعی تحت عنوان renderWays را بر میگرداند که وظیفه اصلی آن نمایش راه هاست. سپس با استفاده از API طراحی شده در بخش قبل و با استفاده از نشان های دریافتی مسیر متناسب گذرنده میان نشان ها را دریافت میکند. برای نمایش مسیر شما باید در صورتی که راه در در حال رسم بخشی از مسیر پیش بینی شده بود پراپرتی مناسب را به آن پاس دهید.

همچنین تابع دیگری تحت عنوان getDistance نیز برمیگرداند که مسافت طی شده را بر حسب متر با استفاده از تابع calcDistance محاسبه کرده و حاصل آن را بر میگرداند.

هوک useMap

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

  • تابعی تحت عنوان renderMap برای رندر کردن تمام المان ها

  • تابع اضافه کردن نشان بر روی نقشه

  • تابع حذف نشان های روی نقشه

کامپوننت <Distance />

هدف از طراحی این کامپوننت نشان دادن مسافت پیموده شده با دقت دو رقم اعشار، نشان ها میباشد که باید درون یک تگ span به صورت زیر نشان داده شود:

distance = 1.25 km 
Plain text

در صورتی که فاصله قابل تبدیل به km بود باید به صورت km ای نشان داده شود (یعنی اگر بزرگتر از 1000 متر بود) در غیر این صورت به صورت همان متر نشان داده شود:

distance = 924.56 m
Plain text

که مقدار مسافت پیموده شده برحسب متر در قالب prop ای تحت عنوان distance پاس داده میشود:

<Distance distance={123.56} />
React JSX
کامپوننت <MapWidget />

این کامپوننت دو پراپ تحت عنوان های deleteMarkers که یک تابع است که عمل پاک کردن مارکر ها را انجام میدهد و دیگری فاصله بر حسب متر یا همان distance می باشد. حال شما باید این کامپوننت را به نحوی تکمیل کنید که پراپها به نحو درست به کامپوننت های <Distance /> و <ClearButton /> پاس داده شوند و هردوی آنها درون <Row> </Row> قرار بگیرند

کامپوننت <Map />

در گام آخر در این کامپوننت شما باید با استفاده از هوک useMap طراحی شده نقشه را در درون <Relative/> با کلاس map نمایش دهید و همچنین در صورتی که بر روی آن کلیک شد باید یک نشان به مجموعه نشان ها اضافه شود. و یک کامپوننت دیگر یعنی همان <MapWidget /> با پراپ های مطلوب نمایش داده شود. و همچنین هردوی این کامپوننتها باید درون تگ <div> قرار بگیرند

موارد پیاده شده🔗

کامپوننت <Marker/>

به عنوان پراپهای ورودی متغییرهای x و y را که بیانگر فاصله از سمت چپ و بالا می باشند دریافت میکند، و یک المان به صورت absolute به عنوان marker را نمایش میدهد

کامپوننت <Row/>

یک ردیف ایجاد می کنید و هیچ ورودی دریافت نمی کند

کامپوننت <ClearButton />

به عنوان ورودی یک تابع onClick میگیرد

کامپوننت <Relative/>

یک المان با استایل relative نمایش میدهد

کامپوننت <Way />

به عنوان ورودی شناسه src و dst را دریافت کرده و متغیر bool تحت عنوان isPath نیز دریافت میکند که بیانگر مسیر بودن یا نبودن می باشد

کامپوننت <Node />

به عنوان ورودی طول و عرض جفرافیایی را در قالب lat و lon دریافت کرده علاوه بر آن مربع در برگیرنده را تحت عنوان bounds دریافت کرده و همچنین شناسه موقعیت جغرافیایی را نیز دریافت میکند.