<details class="red">
<summary>
**این سوال صرفاً برای آموزش کار با سیستم داوری است و هیچ تاثیری در نتیجهی مسابقه ندارد.**
</summary>
</details>
+ محدودیت زمان: ۱ ثانیه
+ محدودیت حافظه: ۲۵۶ مگابایت
----------
در این سوال به شما دو عدد صحیح مثل $a$ و $b$ داده میشود. از شما میخواهیم برنامهای بنویسید که مقدار $a$ و $b$ را دریافت کند و $a + b$ را چاپ کند.
# ورودی
در تنها سطر ورودی، دو عدد صحیح $a$ و $b$ که با یک فاصله از هم جدا شدهاند، داده میشود.
$$1 \leq a, b \leq 100$$
# خروجی
در تنها سطر خروجی، مقدار $a + b$ را چاپ کنید.
# مثالها
## ورودی نمونه ۱
```
3 5
```
## خروجی نمونه ۱
```
8
```
## ورودی نمونه ۲
```
1 1
```
## خروجی نمونه ۲
```
2
```
<details class="yellow">
<summary>
**راهحل JavaScript**
</summary>
```js code.js
var s = readline();
var [a, b] = s.split(' ').map(Number);
console.log(a + b);
```
</details>
<details class="green">
<summary>
**راهحل Node.js**
</summary>
```javascript code.js
const readline = require('readline');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
rl.question('', (s) => {
const [a, b] = s.split(' ').map(Number);
console.log(a + b);
rl.close();
});
```
</details>
<details class="blue">
<summary>
**راهحل TypeScript**
</summary>
```ts code.ts
let s: string = readline();
let [a, b]: number[] = s.split(' ').map(Number);
console.log(a + b);
```
</details>
جمع دو عدد
+ محدودیت زمان: ۱ ثانیه
+ محدودیت حافظه: ۲۵۶ مگابایت
----------
مهیار به ستکردن رنگ لباسها و وسایلش اهمیت زیادی میدهد. او میداند رنگهای مکمل ستهای قشنگی میسازند، ولی نمیتواند با داشتن یک رنگ، رنگ مکمل آن را تشخیص دهد.
مهیار میداند هر رنگ را میتوان از ترکیب سه رنگ اصلی قرمز، سبز و آبی نشان داد. میزان حضور هر کدام از این رنگها را با عددی بین ۰ تا ۲۵۵ نشان میدهند. در واقع هر رنگ را میتوان با سهتایی مرتب $(r, g, b)$ که $0 \leq r, g, b \leq 255$ است، نشان داد.
![نمودار ون RGB](https://quera.org/qbox/view/vnloRcXSa1/Venn_diagram_rgb.svg.png)
برای نمایش کد رنگها، اعداد $r$ و $g$ و $b$ را با دقیقاً ۲ رقم در مبنای ۱۶ پشت سر هم مینویسیم. همچنین علامت `#` قبل از همه این ارقام و حروف به نشانه عدد بودن قرار میگیرد.
برای مطالعهی بیشتر دربارهی اعداد مبنای ۱۶ این [پیوند](https://blog.faradars.org/%D8%B3%DB%8C%D8%B3%D8%AA%D9%85%E2%80%8C%D9%87%D8%A7%DB%8C-%D8%A8%D8%A7%DB%8C%D9%86%D8%B1%DB%8C-%D8%A8%D9%87-%D8%B2%D8%A8%D8%A7%D9%86-%D8%B3%D8%A7%D8%AF%D9%87-%D8%A8%D8%AE%D8%B4-%D8%B3%D9%88/) را مطالعه کنید.
دو رنگ مثل $(r_1, g_1, b_1)$ و $(r_2, g_2, b_2)$ را *مکمل* مینامیم اگر و تنها اگر $r_1 + r_2 = 255$ و $g_1 + g_2 = 255$ و $b_1 + b_2 = 255$ باشد. به شما کد رنگ داده میشود و از شما میخواهیم کد رنگ مکمل آن را با ساختار گفته شده، چاپ کنید.
# ورودی
در سطر اول ورودی، عدد صحیح و مثبت $t$ آمده که تعداد رنگهایی که در یک ورودی داده میشود را نشان میدهد.
$$1 \leq t \leq 10\,, 000$$
در هر کدام از $t$ سطر بعدی، یک رشته به معنی کد رنگ، مثل $s$ آمده که با کاراکتر `#` شروع میشود و در ادامه آن ۶ کاراکتر که میتواند `0` تا `9` یا `A`تا `F` باشد.
# خروجی
در $t$ سطر به ترتیب، کد رنگ مکمل $s$ را با ساختار گفته شده، چاپ کنید.
# مثالها
## ورودی نمونه ۱
```
3
#FFFFFF
#11E43D
#A12FDB
```
## خروجی نمونه ۱
```
#000000
#EE1BC2
#5ED024
```
رنگ مکمل
مهیار پس از اینکه نتوانست در شرکتی کار پیدا کند، با چالشی مواجه شد: شرکت همکاران سیستم اعلام کرد که اگر بتواند تسک زیر را فقط و فقط **در یک خط** و بدون استفاده از _semicolon_ (یعنی `;`) بنویسد، تیم همکاران سیستم وی را با حقوق و مزایای عالی استخدام خواهد کرد. اما مهیار برنامهنویس خوبی نیست و حالا دست به دامن شما شده است که به او کمک کنید.
![آزمون استخدامی همکاران سیستم](https://quera.org/qbox/view/VDtnzMwIZe/sg-azmoon-2.jpg)
شرکت همکاران سیستم بعد از برگزاری یک آزمون استخدامی و ذخیره کردن اطلاعات کاربران در قالب یک فایل *CSV*، به این نتیجه رسید که میتواند هر فرد درخواست دهنده را به صورت زیر در نظر بگیرد:
+ نام (رشته)
+ نام خانوادگی (رشته)
+ سن (عدد صحیح)
+ نمره در آزمون ورودی (رشته)
پس از بدست آوردن لیست افراد واجد شرایط باید آنها را به نحو مطلوب تبدیل شوند:
+ نام باید با حرف اول بزرگ و سایر حروف کوچک نوشته شود.
+ نام خانوادگی با حرف اول بزرگ و سایر حروف کوچک نوشته شود.
+ سن باید در قالب عدد صحیح بدون اعشار نمایش داده شود.
+ نمره کسب شده در آزمون ورودی در قالب عدد صحیح بدون اعشار نمایش داده شود.
اما همکاران سیستم برای محدود کردن لیست اسامی افراد قبول شده، محدودیت سن و نمره در نظر گرفته است. به این معنا که سن افراد **حداکثر** برابر سن خواسته شده یا همان *age* باشد. همچنین **حداقل** نمره افراد واجد شرایط باید برابر نمره خواسته شده شرکت یا همان *score* در نظر گرفته بشود.
در نهایت، پس از بهدست آوردن لیست افراد به نحو مطلوب، باید آنها را در خروجی ترمینال نمایش دهید.
# ورودی
در سطر اول ورودی، تعداد کل افراد یعنی $n$ وارد میشود.
$$1 \leq n \leq 100$$
در سطر دوم ورودی، حداکثر سن مورد نظر وارد میشود.
$$ 18 \le age \le 100$$
در سطر سوم ورودی، حداقل نمره مورد نظر وارد میشود.
$$ 0 \le score \le 100 $$
و در $n$ سطر بعدی، اطلاعات کاربران به ترتیب و با `,` از یکدیگر دیگر جدا شده وارد میشود:
1. نام
2. نام خانوادگی
3. سن
4. نمره
# خروجی
خروجی باید آرایه مرتب شده از لیست افراد که در قالب یک شی به صورت زیر بیان می شود:
```ts
interface Person {
name: string,
family: string,
score: number,
age: number
}
```
# مثالها
## ورودی نمونه ۱
```
4
25
50
Ali,PishGard,23,87
AmiN,AnvArI,25,34
MahYar,RiaZati,26,73
Ali,ShafiEe,13,41
```
## خروجی نمونه ۱
```js
[ { name: 'Ali', family: 'Pishgard', age: 23, score: 87 } ]
```
## آنچه باید آپلود کنید
یک فایل با نام `main.js` که تابعی تحت عنوان `convert` بنویسید که اعمال فوق را تنها و تنها در یک خط بدون استفاده از `;` انجام دهد.
کد بهینه
![ظاهر برنامه](https://quera.org/qbox/view/9t8marsIpu/image.png)
پروژهی اولیه را از [این لینک](/contest/assignments/71326/download_problem_initial_project/243930/) دانلود کنید.
<details class="green">
<summary>
ساختار فایلهای پروژه
</summary>
```
hamkaran-game
├── index.html
└── <mark>style.css</mark>
```
</details>
همکاران سیستم به صورت درون سازمانی یک بازی ویدیویی به شدت جذاب و اکشن توسعه داده است که تیمهای مختلف بتوانند با یکدیگر به رقابت بپردازند. هر تیم میتواند به تعداد دلخواهی اعضا داشته باشد و هدف این بازی همچون بازیهای محبوبی مثل *PUBG* و *COD* این است که دو تیم در کسب بیشترین امتیاز با یکدیگر رقابت داشته باشند شیوه کسب امتیاز در این بازی به چند صورت امکان پذیر است:
- چه تعداد از افراد تیم مقابل را کشتهاید (*Kills*)
- کمک کردن در کشته شدن نفر تیم مقابل (*Assists*)
- نجات دادن افراد تیم خودتان در صورت مجروح شدن (*Revive*)
بنابراین در گام اول، تیم فنی همکاران تصمیم گرفته است تا قبل از آمادهسازی زیرساخت سمت سرور این بازی، برای نمایش اطلاعات یک *UI* نسبتا ساده اما جذاب پیاده سازی شود. خوشبختانه مهیار قبلا ساختار کلی کد *HTML* را برای شما فراهم نموده است اما متاسفانه وی در باقی مباحث فرانت همچون *CSS* و *JS* هیچی بلد نیست و حال دست به دامن شما شده است.
- مهیار میخواهد بخش *footer* پروژه همواره در پایین صفحه ثابت باشد و صد درصد عرض صفحه را نیز پوشش دهد.
- مهیار برای ساماندهی به المانهای طراحی شده تصمیم گرفت یک المان `div` با کلاس `teams` درست کند که در برگیرنده جدول امتیازات دو تیم موجود در صفحه باشد. مهیار میخواهد شما کلاس `.teams` را به نحوی مقداردهی کنید که دو تیم به صورت افقی با فاصله بین هم در کنار یکدیگر قرار بگیرند.
- همچنین هر تیم با کلاس `.team` باید به صورت حداقل ۴۵ درصد عرض کل صفحه نمایش را اشغال کند.
- در گام بعدی شما باید استایلدهی جدول را به نحوی تغییر دهید که مانند تصویر فوق فاصله درستی از چپ و راست داشته داشته باشد. همچنین سطرهای زوج رنگ `rgb(235, 235, 235)` را دارا باشند (باقی سطرها دست نخورده باقی بمانند).
- هر جدول، عرضی معادل ۹۰% را دارا است و باید فاصله خارجی جدول به نحوی تعیین شود که مطابق شکل فوق شود.
- حاشیه جدول باید مطابق تصویر باشد عرض `1px` با استایل `solid` و رنگ `black`.
- یک تگ `div` با کلاس `.status` نیز وجود دارد که وظیفه آن نمایش تیم برنده در حال حاضر است که باید به اندازه`100px` از بالا با المان قبلیش فاصله داشته باشد.
## نکات
- شما تنها مجاز به اعمال تغییرات در فایل `style.css` هستید.
- فایل مذکور به صورت خام یا فشرده `.zip` آپلود نمایید.
بازی همکاران I
![ظاهر برنامه](https://quera.org/qbox/view/9t8marsIpu/image.png)
پروژهی اولیه را از [این لینک](/contest/assignments/71326/download_problem_initial_project/243931/) دانلود کنید.
<details class="green">
<summary>
ساختار فایلهای پروژه
</summary>
```
hamkaran_game_js
├── index.html
├── <mark>index.js</mark>
├── package.json
├── package-lock.json
├── server
│ └── index.js
└── style.css
```
</details>
<details class="blue">
<summary>
راه اندازی پروژه
</summary>
فایلهای پروژه اولیه را دانلود و از حالت فشرده خارج نمایید.
سپس دستور زیر را برای نصب پکیجها و وابستگیها در پوشه پروژه درون ترمینال خود وارد نمایید:
```bash
npm i
```
در نهایت برای راه اندازی سرور سوال دستور زیر را وارد نمایید:
```bash
node server
```
</details>
## توضیحات
زمانی که شما مشغول طراحی و پیادهسازی *UI* بودید مهیار هم اندکی *JS* یادگرفت و به یاری تیم فنی همکاران سیستم شتافت تا زیرساخت این رقابت را در قالب یک *API* فراهم کنند.
این *API* دارای دو *endpoint* است که به شرح زیر است:
اندپوینت اول با آدرس زیر که درخواستی از نوع *GET* را دریافت میکند و نام تیمها به همراه *ID* اشان را برمیگرداند:
```js
const URL = "http://localhost:3000/teams";
[
{
"id": "N12C54612D",
"name": "👨🔧 Engineers 👩🔧"
},
{
"id": "AJ65MD2312",
"name": "👩🦱 Human Resources 👨🦱"
}
]
```
اندپوینت دوم با آدرس زیر که درخواستی از نوع *GET* را دریافت میکند و اطلاعات اعضای حاضر در مسابقه را برمیگرداند:
```js
const URL = "http://localhost:3000/scoreboard";
[
{
"name": "Abolfazl_AJ6",
"team": "AJ65MD2312",
"kills": 16,
"revives": 13,
"assists": 12,
"deaths": 18
},
{
"name": "Maryam_N12",
"team": "N12C54612D",
"kills": 4,
"revives": 2,
"assists": 4,
"deaths": 14
},
///...
]
```
همانطور که مشاهده میکنید اعضا تیمهای برحسب *ID* میباشند نه نام تیم.
## پیاده سازی
وظیفه اصلی شما این است که بر اساس اطلاعات دریافتی جدول امتیازات هر تیم را به صورت جداگانه پیادهسازی نماید.
استراکچر جدول امتیازات هر تیم به صورت زیر است:
```html
<div class="team" id="TEAM_ID">
<h2>TEAM NAME</h2>
<table>
<tr>
<th>Rank</th>
<th>Name</th>
<th>Kills</th>
<th>Assists</th>
<th>Revives</th>
<th>Deaths</th>
<th>Score</th>
</tr>
<tr>
<td>USER RANK</td>
<td>USER NAME</td>
<td>USER KILLS</td>
<td>USER ASSISTS</td>
<td>USER REVIVES</td>
<td>USER DEATHS</td>
<td>USER SCORE</td>
</tr>
</table>
</div>
```
همانطور که مشاهده کردید در اطلاعات دریافتی مقدار امتیاز ذکر نشده است و برای محاسبه امتیاز هر فرد باید از فرمول زیر استفاده نمایید:
$$
score = kills \times 100 + revives \times 75 + assists \times 50
$$
برای محاسبه رتبه هر فرد در تیم خودش یا همان *Rank* کافی است افراد تیم را فقط و فقط بر حسب امتیازشان مرتب نمایید همچنین تضمین میشود امتیاز هیچ دو فردی برابر نخواهد بود.
همچنین تیم همکاران خیلی به اموجیها علاقه دارد و معتقد است یکی از راههای کم هزینه و سریع برای زیباسازی وبسایتها استفاده از اموجی است به همین جهت:
- برای نمایش رتبه نفر اول به جای عدد از 🥇باید استفاده کنید.
- برای نمایش رتبه نفر دوم به جای عدد از 🥈باید استفاده کنید.
- برای نمایش رتبه نفر سوم به جای عدد از 🥉باید استفاده کنید.
در گام آخر شما باید درون `div.status` نام تیم برنده را نمایش دهید. تیمی برنده است که مجموع امتیازات کسب شده اعضای آن بیشتر باشد همچنین تضمین میشود امتیازات دو تیم برابر نخواهند بود.
## آنچه باید آپلود کنید
- شما میتوانید از فایل `style.css` که در بخش قبل تکمیل نمودید در اینجا استفاده کنید.
- شما تنها مجاز به اعمال تغییرات در فایل `index.js` میباشید.
- فایل مذکور به صورت خام یا فشرده `.zip` آپلود نمایید.
بازی همکاران II
![ظاهر برنامه](https://quera.org/qbox/view/hgRMniVxzs/F2.png)
پروژهی اولیه را از [این لینک](/contest/assignments/71326/download_problem_initial_project/243949/) دانلود کنید.
<details class="green">
<summary>
ساختار فایلهای پروژه
</summary>
شما تنها مجاز به انجام تغییرات در فایلهای علامت زده میباشید
```
Zero-Trust-Rooms
├── index.html
├── package.json
├── postcss.config.js
├── server
│ ├── index.js
│ └── package.json
├── src
│ ├── encryption.ts
│ ├── main.ts
│ ├── memory.ts
│ ├── room.ts
│ ├── socket.ts
│ ├── style.css
│ └── vite-env.d.ts
├── tailwind.config.js
└── tsconfig.json
3 directories, 14 files
```
</details>
<details class="blue">
<summary>
راه اندازی پروژه و سرور
</summary>
- فایلهای پروژه اولیه را دانلود و از حالت فشرده خارج نمایید
- سپس دستور زیر را برای نصب پکیجها و وابستگیها در پوشه پروژه درون ترمینال خود وارد نمایید:
```bash
cd initial && npm i
```
- در نهایت برای راه اندازی سرور سوال دستور زیر را وارد نمایید:
```bash
cd server && npm i
node index.js
```
</details>
<details class="red">
<summary>
نکات
</summary>
هر قسمت سوال شامل دو بخش میباشد
### منطق و پیاده سازی الگوریتمها
+ پیاده سازی مربوطه توابع و کلاسها که امضای آنها درون هر فایل به صورت مجزا قرار داده شده است.
+ شما موظف هستید که تابع را بر حسب خواسته آن بخش تکمیل نمایید.
+ رعایت کردن تایپها **الزامی** است!
+ تمامی توابع، متغیرها و کلاسهایی که export شدهاند و یا دارای متدهای عمومی (`public`) میباشند، توسط سیستم داوری بررسی و نمره دهی میشوند.
### پیاده سازی رابط کاربری
+ ساختاری کلی رابط کاربری از قبل با استفاده از کتابخانه tailwind پیاده شده است.
+ برای بعضی از بخشها (مانند نمایش پیام) یک ساختار کلی برای شما تدارک دیده شده است و میتوانید از آن استفاده نمایید.
+ در بخشهایی که شروط خطا ذکر شده است، باید پیغام خطا درون `div#logs` نمایش داده شوند.
+ پیاده سازی این بخش اجباری بوده و توسط سیستم داوری خودکار نمره دهی میشود.
### کتابخانههای مورد استفاده و مجاز در این تمرین
در این سوال شما تنها مجاز به استفاده از کتابخانههای زیر میباشید:
+ پکیج [axios](https://www.npmjs.com/package/axios)
+ پکیج [socket.io-client](https://www.npmjs.com/package/socket.io-client)
+ پکیج [crypto-js](https://www.npmjs.com/package/crypto-js)
+ پکیج [node-rsa](https://www.npmjs.com/package/node-rsa)
</details>
# مقدمه
ماجرا از این قرار است که مهیار نه تنها به هیچکس، حتی خودش اعتماد ندارد بلکه به نرمافزارها نیز اعتماد ندارد. به همین منظور، قصد دارد یک پیامرسان بسیار امن با رمزگذاری سرتاسری (***End To End Encryption*** یه به اختصار ***E2EE***) راهاندازی کند. در این پیامرسان پیامها به صورت کاملا رمزگذاری شده به ازای هر فرد بین کاربران ارسال میشود.
از دیگر قابلیتهای این پیامرسان امکان ایجاد گروه است! حتی چتهای شخصی در قالب یک گروه صورت میگیرند، در این پیامرسان از گروهها به عنوان اتاق (Room) یاد میشود.
همچنین این پیامرسان هیچ اطلاعاتی را نه در سمت سرور و نه در سمت کاربر نگه داری نمیکند فلذا بدین معنا است که پس از بسته شدن مرورگر توسط کاربر تمامی اطلاعات فراموششده و پس از بازگشت به برنامه باید اطلاعات مورد نیاز مجددا توسط کاربر وارد شوند.
![معماری برنامه](https://quera.org/qbox/view/QTxtqTW6a6/F1.png)
# حافظه موقت
به منظور مدیریت متغیرها به شیوه صحیح و با رعایت قید ذکر شده نیاز به پیاده سازی یک حافظه متغیر بسیار ساده ***“Key-Value Pair”*** وجود دارد که باید آن را درون فایل `memory.ts` تکمیل نمایید، این حافظه چیزی جز یک` object `ساده نیست که چهار تابع برای مدیریت حافظه مذکور را دار میباشد:
+ تابع `getMemory` که از حافظه موقت یک رونوشت (Copy) را برمیگرداند.
+ تابع `memoryForget` که با دریافت نام کلید آن را از حافظه موقت حذف میکند.
+ تابع` memoryRecall که` با دریافت نام کلید مقدار تعیین شده برای آن کلید را بر میگرداند، در صورتی که کلید مذکور وجود نداشت باید مقدار`undefined` برگردانده شود.
+ تابع `memoryRemember` که با دریافت یک کلید و مقدار که میتواند یک متغیر باشد یا یک تابع که به عنوان ورودی مقدار متغیر قبلی را دریافت کرده و مقدار جدیدی را برمیگرداند، درون حافظه مقدار کلید را تنظیم و یا باز تنظیم کند.
# اطلاعات کاربر
+ برای این که کاربر بتواند از این برنامه طراحی شده استفاده کند باید اطلاعات زیر را درون مرورگر در قالب یک فایل `.`json با کلیدهای زیر بارگذاری نماید:
1. نام کاربری که درون فیلد` name `وارد میشود و از جنس رشته میباشد و باید حداقل ۳ کارکتر باشد در صورتی که طول رشته کمتر از ۳ بود باید ارور با پیغام زیر برگردانده شود:
```
"username" must be at least 3 characters
```
2. کلید عمومی (***Public Key***) که درون فیلد `public` در قالب یک رشته میباشد.
3. کلید شخصی (***Private Key***) که درون فیلد` private` در قالب یک رشته میباشد.
+ در صورتی که کاربر هر یک از فیلدهای زیر را وارد نکرده بود باید اروری با پیغام زیر برگردانده شود:
```
You did not provide "<FIELD_NAME>"
```
+ همچنین در مورد کلیدهای شخصی و عمومی این رشته کدگذاری شده باید موارد زیر بررسی و صحت سنجی شوند:
+ آیا کلیدهای ارسالی از نوع `RSA256` میباشد؟ در غیر این صورت اروری با پیغام زیر برگردانده شود
```
Keys are not RSA256
```
+ آیا کلیدها با یکدیگر همخوانی دارند؟ در صورت کلیدها با یکدیگر همخوانی نداشتند ارور با پیغام زیر برگردانده شود:
```
Invalid Key Pairs
```
## مثال ورودی
-برای مثال فایلی با محتوای زیر تمامی شرایط فوق را دارا میباشد:
```json
{
"name": "Mahyar",
"public": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A0UaGNOz5e6QmGl63GgP\nWHw8xFE+r2MYVeGVGP2OD9juhIXg3ePOvSw8sakGprESFz7shkNCeAQ8q+affSeA\n8+u83Gn+twjnxij99nQ+fgdpHZN4WYzruJ2N76kxUYm5oMfYjU+Ao\nfxxl4E+q3UXZAQ/hnq/nNLAylnsxs175eaH0wFf9q80smAcCUaE/0CzRTDaw4bHi\nkFiUcpnVWFM7TiRHFWmNXIF2srAqA+jEPRQ+yjtCuDA9NdmRnAdFLItQI9UdnnV7\nj96hqWXcAgQDlr4NTyX1aNjaKFzuRz/w6F0P03UOVHP6okUGp6vjmsv/3sY6AydE\nTwIDAQAB",
"private": "MIIEowIBAAKCAQEA70UaGNOz5e6QmGl63GgPWHw8xFE+r2MYVeGVGP2OD9juhIXg\n3ePOvSw8sakGprESFz7shkNCeAQ8q+affSeA8+u83Gn+twjnxij99nQ+fgdpHZN4\nWYzruJ2NpWw0Zcm4wdZ76kxUYm5oMfYjU+Aofxxl4E+q3UXZAQ/hnq/nNLAylnsx\ns175eaH0wFf9q80smAcCUaE/0CzRTDaw4bHikFiUcpnVWFM7TiRHFWmNXIF2srAq\nA+jEPRQ+yjtCuDA9NdmRnAdFLItQI9UdnnV7j96hqWXcAgQDlr4NTyX1aNjaKFzu\nRz/w6F0P03UOVHP6okUGp6vjmsv/3sY6AydETwIDAQABAoIBAE0H1zYE+hbdbinT\nU52f1sjq/nlJmr/GTHBhtqmb/990PJ3nqBRnoghfNI8R1rVVrnhTZrx27PBMlOfW\n0KPvUuG0lFH1we5VbKDsU47Dr9bNNfcyof1alA0UlCScqGXYwqWNEsnElyo1V1A2\naPs44HDDyLyliWHBefKQlVeMVgLs4f2QkidpUD5djPx38ObKknmP\nnSm2uVedP+KxC/uD7AwwWIKAw/XrIppWHZE1a+//NwsJOnZ2UwWp4QM41K/RZzgA\nwyMQ3Tl9SDCfNmm4Gs0OmF73V959B7yC4k3iTUJpRnru6wJVrOEIj2LcSUwPbI0c\nxSK7NZECgYEA+S/D4bQ9Afu8PGCide1F5wvtJy852pTsCnUnZLyA59KY9U\nbTvY468OH7le9zdDS93KC0QOEMESw75KJ+Ntd9BH5eW4PP8/7fvGIjAWPest0SFq\nzuHznchRYhs09/0BFGbGg2/FxeRUYazQ9sPy94+E9VRGlA14cph5DAkCgYEA9c/s\nTG7mJnuFP+KPJ76llpA68HhtBSmCYJLyr/jhqTOPIMQ+qQlENm2tc/zkMF43ciE6\n2wbXLteq/FKcGIbK/vXiCka1RCm9bbZ/be4IV9prdvm3MuTKUKjJQOdg2adwlM0Q\nRm+jvyr65GZ6U/IEgN519+cNfEE/ICwX3ikYk5cCgYEAw3j2vg03dmDVLr/Xihhl\n8MxtlUZoRyirR/O7pq12FDf8BnlnMbzfy7iQ0Tq3Z6dwmZleTxsyrVe7eOUcJTUW\n0ueTLdPTMsLbne3VZoiEyrjSGcxs6oq+UH/rLTDAtqcFDCwKNsjQnLaHfE866kw4\nt/rKk+yfrhtoKifO/oYhHpECgYB4YUYovFrL18wO2EYhQbVYQfQLVf6V+5kU8IIX\nebwRn+VlN5Y0NAyK1zWNyvh5U3q10t4+61+wWgArp804GbMKH6J+Q9h7tDFHrItF\na7/8PkRItMxqCS+nRrGgrm94yA5TYQWqaPv5H/RUrHcV6z0XW1rMeAPbqRxgBhf+\nPYQCqwKBgAfn3oxLjx0mSjtr2iDIaMHoZQq5Dl97ac3+nMpqEUJVS/F6bHRE4eTz\ni/NrMSJzwuMOrMFVBKpnDc9STsRuv+oGvoxeXA4taGlJVj5lAa83b0PEKCQV9Uzn\nk4K/8DCEKqLQPtXQI0Xdszx344RLINELoVm3p3jSFEyaOTK40uvp"
}
```
## پیاده سازی
برای تکمیل این قسمت شما باید موارد زیر را تکمیل نمایید
### فایل `encrypt.ts`
در این فایل شما باید `isValidData`از کلاس `EncryptionService` را تکمیل نمایید بدین نحو که با دریافت کردن اطلاعات کاربر در قالب یک `Object` ، خطاها را در صورت وجود در قالب یک آرایه شامل رشتهها برگرداند و درصورتی که هیچ مشکلی در داده ورودی نبود آرایه خالی برگرداند.
### فایل `main.ts`
در این فایل شما باید قابلیتی را پیاده سازی کنید در هنگامی که کاربر فایل جدید را در `#file-upload` بارگذاری کرد آن را صحت سنجی کرده و آن را درون حافظه با کلید `credentials` ذخیره نماید. و در صورت بروز خطا، خطاها را به کاربر نمایش دهد. همچنین در صورتی که فایل دارای مشکل بود باید پیغام زیر به کاربر نمایش داده شود:
```
File is Not Valid
```
# اتاقهایی برای گفتوگو
همانطور که قبلا ذکر شد در این پیامرسان، مفهومی تحت عنوان اتاق وجود دارد که میتواند حداقل یک عضو داشته باشد. تمامی افراد میتوانند به شرط داشتن گذرواژه وارد این اتاقها شوند، البته فردی که اتاق را در ابتدا درست کرده است، میتواند به نحو خاصی که در ادامه به آن اشاره خواهد شد، فقط به افراد به خصوصی امکان اجازه دسترسی بدهد حتی اگر رمز و نام اتاق را به نحوی به دست آورده باشند این مکانیزم منجر به این قضیه خواهد شد تا افراد فاقد صلاحیت نتوانند وارد اتاق شوند.
## ایجاد و عضویت
همانطور که ذکر شد، کاربر برای ایجاد و یا عضویت در اتاق باید نام اتاق (`roomName`) به همراه گذرواژه (`password`) و کلید عمومی خود را در قالب یک شی به سمت سرور ارسال کند:
```ts
interface Request{
roomName: string;
password: string;
publicKey: string;
}
```
### مسیر `/api/join/`
در گام اول، کاربر اطلاعات مذکور را به آدرس `/api/join/` ارسال میکند و با یکی از سه سناریوی زیر مواجه میشود:
1. در صورتی که کاربر اطلاعات را به درستی وارد کرده باشد ولی با خطای ***404*** مواجه شود، باید همان اطلاعات را به مسیر `/api/create/` ارسال کند و پس از ایجاد، مجدداً درخواست اول تکرار و ارسال شود.
2. در صورتی که گذرواژه به اشتباه وارد شده باشد، باید پیغامی با محتوای زیر در `div#request-status` نمایش داده شود:
```
Bad Credentials!
```
3. در صورتی که کاربر امکان دسترسی به گروه درخواست شده را نداشته باشد، در همان `div#request-status` پیغام زیر نمایش داده شود:
```
Unauthorized Access!
```
### مسیر `/api/create/`
کاربر اطلاعات زیر را به آدرس `/api/create/` ارسال میکند تا یک اتاق جدید ایجاد کند:
```ts
interface CreateRequest {
groupName: string;
password: string;
publicKey: string;
}
```
اگر ایجاد اتاق موفقیتآمیز باشد، سرور یک پیام موفقیت با محتوای زیر به کاربر بازمیگرداند:
```
Room created successfully!
```
در غیر این صورت، باید خطای دریافتی از سمت سرور درو `div#request-status` نمایش داده شود.
## مدیریت اتاق
الزاما داشتن نام اتاق و گذرواژه آن راه مطلوبی برای تضمین امنیت گروهها نیست زیرا در صورتی که اطلاعات حساس اتاق وصل شود هر فردی میتواند به این اتاق دسترسی پیدا کند به همین منظور مهیار تصمیم گرفت که برای مدیریت این قضیه قابلیتی اضافه کند تا افرادی که دارای صلاحیت هستند را با استفاده از کلید عمومی آنها به گروه اضافه کند برای این منظور باید به درخواست زیر ارسال شود:
```
// PUT /api/room/
interface AddUserRequest {
Request;
user: string; // new user public key
}
```
+ در صورتی که اتاق وجود نداشت باید خطایی با پیغام زیر برگردانده شود:
```
Room Not Found!
```
+ از آنجایی که فقط فردی که گروه را ایجاد کرده میتواند افراد جدید را اضافه کند، در صورتی که کاربر، ایجاد کننده اتاق نباشد باید خطایی با پیغام زیر برگردانده شود:
```
Forbidden: Not the owner of the room
```
## پیاده سازی
- موارد خواسته شده در خصوص ***API*** ها و ارتباط با سرور را در فایل `room.ts` تکمیل نمایید
- همچنین برای رابط کاربری فایل `main.ts` مطابق فیلدهایی که در فایل `index.html` عملکرد مطلوب را پیاده سازی کنید
# اتصال به سوکت برای ارسال و دریافت پیام
برای ارتباط بلادرنگ، کاربران باید به یک ***WebSocket*** متصل شوند که پیاده سازی آن در فایل `socket.ts` باید صورت بگیرد. برای این کار، باید از آدرس زیر استفاده شود و باید `token` حاصل شده از بخش قبلی را در بخش احراز هویت Header ارسال نماید:
```
/ws/room/<ROOM_NAME>/
```
پس از اتصال موفق، کاربر کلید عمومی همراه با نام خود و شناسه اتصال سوکت را برای تمامی کاربران حاضر در اتاق در قالب یک رخداد تحت عوان ` publicKey ` ارسال مینماید. همچنین باقی کاربران پس از دریافت باید اطلاعات خود را نیز در قالب همان رخداد ارسال نمایند.
## شیوه ارسال پیام
+ در گام صفرم کاربر باید محتوای پیام خود را درون `input` مربوطه بنویسید و سپس دکمه `Send` را فشرده تا روند اصلی ارسال آغاز شود.
+ در گام اول باید به ازای تمامی کاربران موجود در اتاق (به غیر از خودتان) پیام ارسالی مورد نظر آنها را با توجه به کلید عمومی هر کاربر رمزگزاری کنید.
+ در گام بعد جهت اینکه مشخص شود این پیام توسط شما ارسال شده است باید آن را با استفاده از کلید خود امضا کنید.
+ در گام بعدی با توجه به به پیام رمزنگاری شده برای دیگر کاربران باید آن را در قالب یک رخداد message پیام رمزگذاری شده را به همراه امضا در قالب یک شی به همراه شناسه کاربر مورد نظر ارسال نمایید.
## شیوه دریافت پیام
+ پس از دریافت یک پیام در گام اول باید این امر صحت سنجی شود که با توجه به اطلاعات دریافتی (پیام رمزگذاری شده و امضای مذکور) آیا این پیام واقعا از آن کاربر آمده است یا خیر؟ در غیر این صورت اروری تحت عنوان زیر نمایش داده شود
```
Message verification failed for sender <SENDER_USERNAME>
```
+ در گام بعد باید پیام دریافت شده باید با توجه به کلید شخصی کاربری که پیام را دریافت کرده است رمزگشایی شده و بازگردانده شود.