# پروژه اولیه
پروژه اولیه را از [این لینک](/contest/assignments/64549/download_problem_initial_project/220471/) دانلود کنید.
ساختار فایلهای این پروژه به صورت زیر است:
```
removeDuplicate
├── src
│ └── <mark>index.js</mark>
├── jest.config.js
├── package-lock.json
└── package.json
```
برای اینکه کادر اجرایی بوتکمپ بتوانند راحتتر و سریعتر به دادههای کدآموزهای بوتکمپ دسترسی داشته باشند، نگهداری و بررسی آنها اهمیت زیادی دارد. اما متاسفانه هنگام وارد کردن این اطلاعات به صورت دستی، مشکلی پیش آمد و اسم بعضی از کدآموزها بیشتر از یک بار وارد شد...!
از طرف مدیر بوتکمپ، تسکی به شما داده شده تا با پیادهسازی تابع `removeDuplicateStudents`، کدآموزهای تکراری را پیدا کنید و فقط یک نسخه از دادههای مربوط به هر کاربر را حفظ و بقیه را حذف کنید.
برای پیادهسازی تابع `removeDuplicateStudents` لازم است به این موارد دقت کنید:
1. این تابع به عنوان ورودی، یک آرایه دریافت میکند.
عناصر این آرایه، آبجکتهایی هستند که هر کدام از آنها مربوط به اطلاعات یک کدآموز است.
2. هر آبجکت مربوط به اطلاعات یک کدآموز دارای پراپرتیهای زیر است:
1. level
2. grade*
3. name*
4. lastName*
5. birthDate*
6. nationality
7. email
3. از ترکیب مقدار پراپرتیهای `grade`، `name`، `lastNam`، `birthDate` میتوان برای مشخص کردن و تفکیک کدآموزها استفاده کرد. به عبارت دیگر نباید هیچ دو کدآموزی با مقادیر برابر این ویژگیها وجود داشته باشند و ترکیب این مقادیر برای هر کدآموز منحصربفرد هستند.
4. در صورتی که چند نسخه از اطلاعات یک کدآموز موجود بود، نسخهای که مقدار پراپرتی `level` در آن بیشتر است، نگهداری میشود و بقیه نسخهها حذف میشوند.
5. در صورتی که مقدار پراپرتی `level` در چند نسخه از اطلاعات یک کدآموز مشترک بود، اولویت با نسخهای که دارای مقدار **index** کمتری است خواهد بود و بقیه نسخهها حذف میشوند.
6. همهی عناصر آرایه خروجی باید دارای یک پراپرتی اضافه با کلید `id` باشند، مقدار `id` از ترکیب مقدار پراپرتیهای `grade`، `name`، `lastNam`، `birthDate` به ترتیب از راست به چپ به دست میآید.
# مثال
در مثال زیر سه نسخه از اطلاعات کاربری به اسم `Jone doe` وجود دارد.
از آنجا که تمامی چهار ویژگی `grade`، `name`، `lastNam`، `birthDate` در این سه شیء برابر هستند، نتیجه میگیریم اطلاعات این کاربر سه بار و به صورت تکراری ذخیره شده است.
برای تشخیص نسخه معتبر، ابتدا ویژگی `level` را بررسی میکنیم و آبجکتی که مقدار `level` بیشتری دارد را نگه داشته و بقیه را حذف میکنیم.
در ادامه دو آبجکت که مقدار پراپرتی `level` در هردوی آنها برابر ۳ است را بر اساس جایگاهشان در آرایه مقایسه کرده و آبجکتی که **index** کوچکتری دارد را نگه داشته و بقیه نسخهها را حذف می کنیم.
نباید فراموش کنیم که در آرایه خروجی، تمامی عناصر آرایه دارای پراپرتی `id` هستند.
مقدار `id` از ترکیب مقادیر پراپرتیهای `grade`، `name`، `lastNam`، `birthDate` به ترتیب حاصل میشود.
## ورودی
```
const studentsArray = [
{
level: 2,
grade: 10,
name: "John",
lastName: "Doe",
birthDate: "2002-05-20",
nationality: "American",
email: "john.doe@example.com"
},
{
level: 3,
grade: 10,
name: "John",
lastName: "Doe",
birthDate: "2002-05-20",
nationality: "American",
email: "john.doe@example.com"
},
{
level: 3,
grade: 10,
name: "John",
lastName: "Doe",
birthDate: "2002-05-20",
nationality: "Iran",
email: "john.doe@example.com"
},
{
level: 3,
grade: 10,
name: "Saimon",
lastName: "Jonse",
birthDate: "2002-06-20",
nationality: "Italy",
email: "Saimon.Jonse@example.com"
},
];
```
## خروجی
```
const studentsArray = [
{
level: 3,
grade: 10,
name: "John",
lastName: "Doe",
birthDate: "2002-05-20",
nationality: "American",
email: "john.doe@example.com",
id: "10JohnDoe2002-05-20"
},
{
level: 3,
grade: 10,
name: "Saimon",
lastName: "Jonse",
birthDate: "2002-06-20",
nationality: "Italy",
email: "Saimon.Jonse@example.com",
id: "10SaimonJonse2002-06-20"
},
];
```
# جزئیات
1. تابع `removeDuplicate` آرایهای از اطلاعات کدآموزها را به عنوان ورودی دریافت میکند.
2. خروجی تابع `removeDuplicate` آرایهای از اطلاعات کدآموزهاست که نسخههای تکراری اطلاعات در آن حذف شده و هر کدام از عناصر آن دارای پراپرتی `id` باشد.
3. شما تنها مجاز به تغییر فایل `index.js` هستید.
4. فایل ارسالی شما باید `index.js` باشد.
در بعضی از سایتها به دلیل حجم بالای درخواستها، ممکن است بعضی از تلاشهای کاربران برای ورود با خطا مواجه شود و کاربر مجدد درخواست ورود را ارسال کند ،حالا ما میخواهیم به صورت خودکار این کار را انجام دهیم تا اطلاعات بیشتری از ورود کاربران دریافت کنیم. این کار کمک میکند بفهمیم **کاربر در چندمین تلاش با موفقیت وارد میشود و چه مقدار زمان طول میکشد تا به نتیجه برسد.**
![توضیح تصویر](https://quera.org/qbox/view/UfqtcPwqoS/sendAndTry.gif)
# پروژه اولیه
پروژه اولیه را از [این لینک](/contest/assignments/64549/download_problem_initial_project/220473/) دانلود کنید.
ساختار فایلهای این پروژه به صورت زیر است:
```
LoginAndTry
├── src
│ └── login.js
│ └── <mark title="تغییرات را تنها در این فایل اعمال کنید">main.js</mark>
├── package.json
```
# جزئیات
اطلاعاتی که در نهایت خواهیم داشت به شکل زیر است:
- **نمایش یک عدد که نشاندهنده شماره تلاش موفق کاربر خواهد بود.**(به عنوان مثال عدد ۳ نشان دهنده ورود موفق کاربر در تلاش سوم است)
- **وضعیت نهایی ورود کاربر** (ورود موفق یا ناموفق بعد از تعداد مشخصی تلاش)
- **مجموع زمان درخواستهای کاربر** (مجموع زمان تلاش های موفق و ناموفق)
در این سوال تابع `login` به شما داده شده است و تنها نیاز است تا تابع `loginAndTry` را پیادهسازی کنید. در ادامه توضیحاتی درباره هر کدام از توابع آورده شده است.
<details class="blue">
<summary>
تابع `login`
</summary>
تمام درخواستهای ورود کاربر توسط تابعی به نام `login` انجام میشود که به عنوان ورودی یک نامکاربری دریافت میکند. این تابع بعد از ارسال درخواست به سرور، یک پاسخ از نوع آبجکت که شامل `status` و `responseTime` خواهد بود را به ما برمیگرداند که به ترتیب وضعیت درخواست و زمان دریافت پاسخ است. (زمان پاسخ بین ۱ تا ۲۰۰ میلیثانیه خواهد بود.)
**نکته:** این تابع در حال حاضر در اختیار شما قرار داده شده است و نیازی به پیادهسازی آن نیست.
</details>
<details class="blue">
<summary>
تابع `loginAndTry`
</summary>
حالا باید با استفاده از تابع `loginAndTry` درخواستهایی که توسط تابع `login` سمت سرور ارسال شدهاند را مدیریت کنید و در نهایت یک آبجکت که شامل مقادیر `try` ،`status` و `timeSpent` است را خروجی بدید.
تابع `loginAndTry` دو ورودی دریافت خواهد کرد که ورودی اول، نام کاربری شخص و ورودی دوم، تعداد تلاشهای مجاز برای این کاربر خواهد بود. (برای جلوگیری از فشار مضاعف روی سرور، تعداد تلاشهای مجدد کاربر حداکثر ۱۰ خواهد بود.) شما باید تابع را به شکلی کامل کنید تا به تعداد دفعات خواسته شده (ورودی دوم تابع) درخواست ورود به سمت سرور ارسال کند و بلافاصله بعد از **اولین درخواست موفق**، مقادیر خواسته شده را برگرداند.
</details>
# مثال
تابع `loginAndTry` را به شکل زیر فراخوانی میکنیم.
```
loginAndTry("myUsername", 5)
```
با استفاده از فراخوانی تابع `login` داخل تابع `loginAndTry` تعدادی درخواست ورود (حداکثر ۵ درخواست) ارسال میکنیم، دو درخواست اول ناموفق است که به ترتیب ۱۱۲ و ۷۲ میلیثانیه زمان برده است. ولی درخواست سوم موفقیتآمیز خواهد بود و زمان پاسخ از سمت سرور ۳۵ میلیثانیه است. پس خروجی نهایی تابع به شکل زیر خواهد بود:
```
{try: 3, status: true, timeSpent: 219}
```
# نکات
1. تابع `loginAndTry` دو مقدار به عنوان ورودی میگیرد. مقدار اول یک رشته که نام کاربری خواهد بود و مقدار دوم یک عدد که حداکثر تعداد درخواست ورود به سرور است.
2. خروجی تابع `loginAndTry` باید یک آبکجت باشد با مقادیر `try`, `status` و `timeSpent` که به ترتیب شماره درخواست موفق، وضعیت نهایی و مجموع مدت زمان درخواستها است.
3. برای ارسال درخواست از تابع `login` استفاده کنید. ورودی این تابع یک رشته خواهد بود که نامکاربری است.
4. بلافاصله بعد از دریافت **اولین درخواست ورود موفق**، باید مقادیر خواسته شده در خروجی نمایش داده شود.
5. در صورتی که هیچیک از درخواستها موفقیتآمیز نبود، مقدار `status` در خروجی نهایی برابر **false** خواهد بود.
6. شما تنها مجاز به اعمال تغییرات در فایل `main.js` هستید و فایل ارسالی شما هم باید `main.js` باشد.