جمع دو عدد


این سوال صرفاً برای آموزش کار با سیستم داوری است و هیچ تاثیری در نتیجه‌ی مسابقه ندارد.
  • محدودیت زمان: ۱ ثانیه
  • محدودیت حافظه: ۲۵۶ مگابایت

در این سوال به شما دو عدد صحیح مثل aa و bb داده می‌شود. از شما می‌خواهیم برنامه‌ای بنویسید که مقدار aa و bb را دریافت کند و a+ba + b را چاپ کند.

ورودی🔗

در تنها سطر ورودی، دو عدد صحیح aa و bb که با یک فاصله از هم جدا شده‌اند، داده می‌شود.

1a,b1001 \leq a, b \leq 100

خروجی🔗

در تنها سطر خروجی، مقدار a+ba + b را چاپ کنید.

مثال‌ها🔗

ورودی نمونه ۱🔗

3 5
Plain text

خروجی نمونه ۱🔗

8
Plain text

ورودی نمونه ۲🔗

1 1
Plain text

خروجی نمونه ۲🔗

2
Plain text
راه‌حل JavaScript
extensionFromNamecode.js
var s = readline();
var [a, b] = s.split(' ').map(Number);

console.log(a + b);
JavaScript
راه‌حل Node.js
extensionFromNamecode.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();
});
JavaScript
راه‌حل TypeScript
extensionFromNamecode.ts
let s: string = readline();
let [a, b]: number[] = s.split(' ').map(Number);
console.log(a + b);
TypeScript

رنگ مکمل


  • محدودیت زمان: ۱ ثانیه
  • محدودیت حافظه: ۲۵۶ مگابایت

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

مهیار می‌داند هر رنگ را می‌توان از ترکیب سه رنگ اصلی قرمز، سبز و آبی نشان داد. میزان حضور هر کدام از این رنگ‌ها را با عددی بین ۰ تا ۲۵۵ نشان می‌دهند. در واقع هر رنگ را می‌توان با سه‌تایی مرتب (r,g,b)(r, g, b) که 0r,g,b2550 \leq r, g, b \leq 255 است، نشان داد.

نمودار ون RGB

برای نمایش کد رنگ‌ها، اعداد rr و gg و bb را با دقیقاً ۲ رقم در مبنای ۱۶ پشت سر هم می‌نویسیم. همچنین علامت # قبل از همه این ارقام و حروف به نشانه عدد بودن قرار می‌گیرد.

برای مطالعه‌ی بیشتر درباره‌ی اعداد مبنای ۱۶ این پیوند را مطالعه کنید.

دو رنگ مثل (r1,g1,b1)(r_1, g_1, b_1) و (r2,g2,b2)(r_2, g_2, b_2) را مکمل می‌نامیم اگر و تنها اگر r1+r2=255r_1 + r_2 = 255 و g1+g2=255g_1 + g_2 = 255 و b1+b2=255b_1 + b_2 = 255 باشد. به شما کد رنگ داده می‌شود و از شما می‌خواهیم کد رنگ مکمل آن را با ساختار گفته شده، چاپ کنید.

ورودی🔗

در سطر اول ورودی، عدد صحیح و مثبت tt آمده که تعداد رنگ‌هایی که در یک ورودی داده می‌شود را نشان می‌دهد. 1t10,0001 \leq t \leq 10\,, 000

در هر کدام از tt سطر بعدی، یک رشته به معنی کد رنگ، مثل ss آمده که با کاراکتر # شروع می‌شود و در ادامه آن ۶ کاراکتر که می‌تواند 0 تا 9 یا Aتا F باشد.

خروجی🔗

در tt سطر به ترتیب، کد رنگ مکمل ss را با ساختار گفته شده، چاپ کنید.

مثال‌ها🔗

ورودی نمونه ۱🔗

3
#FFFFFF
#11E43D
#A12FDB
Plain text

خروجی نمونه ۱🔗

#000000
#EE1BC2
#5ED024
Plain text

کد بهینه


مهیار پس از اینکه نتوانست در شرکتی کار پیدا کند، با چالشی مواجه شد: شرکت همکاران سیستم اعلام کرد که اگر بتواند تسک زیر را فقط و فقط در یک خط و بدون استفاده از semicolon (یعنی ;) بنویسد، تیم همکاران سیستم وی را با حقوق و مزایای عالی استخدام خواهد کرد. اما مهیار برنامه‌نویس خوبی نیست و حالا دست به دامن شما شده است که به او کمک کنید.

آزمون استخدامی همکاران سیستم

شرکت همکاران سیستم بعد از برگزاری یک آزمون استخدامی و ذخیره کردن اطلاعات کاربران در قالب یک فایل CSV، به این نتیجه رسید که می‌تواند هر فرد درخواست دهنده را به صورت زیر در نظر بگیرد:

  • نام (رشته)
  • نام خانوادگی (رشته)
  • سن (عدد صحیح)
  • نمره در آزمون ورودی (رشته)

پس از بدست آوردن لیست افراد واجد شرایط باید آن‌ها را به نحو مطلوب تبدیل شوند:

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

اما همکاران سیستم برای محدود کردن لیست اسامی افراد قبول شده، محدودیت سن و نمره در نظر گرفته است. به این معنا که سن افراد حداکثر برابر سن خواسته شده یا همان age باشد. همچنین حداقل نمره افراد واجد شرایط باید برابر نمره خواسته شده شرکت یا همان score در نظر گرفته بشود.

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

ورودی🔗

در سطر اول ورودی، تعداد کل افراد یعنی nn وارد می‌شود. 1n1001 \leq n \leq 100

در سطر دوم ورودی، حداکثر سن مورد نظر وارد می‌شود.

18age100 18 \le age \le 100

در سطر سوم ورودی، حداقل نمره مورد نظر وارد می‌شود.

0score100 0 \le score \le 100

و در nn سطر بعدی، اطلاعات کاربران به ترتیب و با , از یکدیگر دیگر جدا شده وارد می‌شود:

  1. نام
  2. نام خانوادگی
  3. سن
  4. نمره

خروجی🔗

خروجی باید آرایه مرتب شده از لیست افراد که در قالب یک شی به صورت زیر بیان می شود:

interface Person {
    name: string,
    family: string,
    score: number,
    age: number
}
TypeScript

مثال‌ها🔗

ورودی نمونه ۱🔗

4
25
50
Ali,PishGard,23,87
AmiN,AnvArI,25,34
MahYar,RiaZati,26,73
Ali,ShafiEe,13,41
Plain text

خروجی نمونه ۱🔗

[ { name: 'Ali', family: 'Pishgard', age: 23, score: 87 } ]
JavaScript

آن‌چه باید آپلود کنید🔗

یک فایل با نام main.js که تابعی تحت عنوان convert بنویسید که اعمال فوق را تنها و تنها در یک خط بدون استفاده از ; انجام دهد.

بازی همکاران I


ظاهر برنامه

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

ساختار فایل‌های پروژه
hamkaran-game
├── index.html
└── style.css
Plain text

همکاران سیستم به صورت درون سازمانی یک بازی ویدیویی به شدت جذاب و اکشن توسعه داده است که تیم‌های مختلف بتوانند با یکدیگر به رقابت بپردازند. هر تیم می‌تواند به تعداد دلخواهی اعضا داشته باشد و هدف این بازی همچون بازی‌های محبوبی مثل PUBG و COD این است که دو تیم در کسب بیشترین امتیاز با یکدیگر رقابت داشته باشند شیوه کسب امتیاز در این بازی به چند صورت امکان پذیر است:

  • چه تعداد از افراد تیم مقابل را کشته‌اید (Kills)
  • کمک کردن در کشته شدن نفر تیم مقابل (Assists)
  • نجات دادن افراد تیم خودتان در صورت مجروح شدن (Revive)

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

  • مهیار می‌خواهد بخش footer پروژه همواره در پایین صفحه ثابت باشد و صد درصد عرض صفحه را نیز پوشش دهد.
  • مهیار برای ساماندهی به المان‌های طراحی شده تصمیم گرفت یک المان div با کلاس teams درست کند که در برگیرنده جدول امتیازات دو تیم موجود در صفحه باشد. مهیار می‌خواهد شما کلاس .teams را به نحوی مقداردهی کنید که دو تیم به صورت افقی با فاصله بین هم در کنار یکدیگر قرار بگیرند.
  • همچنین هر تیم با کلاس .team باید به صورت حداقل ۴۵ درصد عرض کل صفحه نمایش را اشغال کند.
  • در گام بعدی شما باید استایل‌دهی جدول را به نحوی تغییر دهید که مانند تصویر فوق فاصله درستی از چپ و راست داشته داشته باشد. همچنین سطرهای زوج رنگ ‍rgb(235, 235, 235) را دارا باشند (باقی سطرها دست نخورده باقی بمانند).
  • هر جدول، عرضی معادل ۹۰% را دارا است و باید فاصله خارجی جدول به نحوی تعیین شود که مطابق شکل فوق شود.
  • حاشیه جدول باید مطابق تصویر باشد عرض 1px با استایل solid و رنگ black.
  • یک تگ div با کلاس .status نیز وجود دارد که وظیفه آن نمایش تیم برنده در حال حاضر است که باید به اندازه1‍0‍0px از بالا با المان قبلیش فاصله داشته باشد.

نکات🔗

  • شما تنها مجاز به اعمال تغییرات در فایل style.css هستید.
  • فایل مذکور به صورت خام یا فشرده .zip آپلود نمایید.

بازی همکاران II


ظاهر برنامه

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

ساختار فایل‌های پروژه
hamkaran_game_js                                                                                
├── index.html                                                                                
├── index.js                                                                                   
├── package.json                                                                               
├── package-lock.json                                                                          
├── server                                                                                     
│   └── index.js                                                                               
└── style.css                                                                                              
Plain text
راه اندازی پروژه

فایل‌های پروژه اولیه را دانلود و از حالت فشرده خارج نمایید.

سپس دستور زیر را برای نصب پکیج‌ها و وابستگی‌ها در پوشه پروژه درون ترمینال خود وارد نمایید:

npm i
Bash

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

node server
Bash

توضیحات🔗

زمانی که شما مشغول طراحی و پیاده‌سازی UI بودید مهیار هم اندکی JS یادگرفت و به یاری تیم فنی همکاران سیستم شتافت تا زیرساخت این رقابت را در قالب یک API فراهم کنند.

این API دارای دو endpoint است که به شرح زیر است:

اندپوینت اول با آدرس زیر که درخواستی از نوع GET را دریافت می‌کند و نام تیم‌ها به همراه ID اشان را بر‌می‌گرداند:

const URL = "http://localhost:3000/teams";

[
    {
        "id": "N12C54612D",
        "name": "👨‍🔧 Engineers 👩‍🔧"
    },
    {
        "id": "AJ65MD2312",
        "name": "👩‍🦱 Human Resources 👨‍🦱"
    }
]
JavaScript

اندپوینت دوم با آدرس زیر که درخواستی از نوع GET را دریافت می‌کند و اطلاعات اعضای حاضر در مسابقه را برمیگرداند:

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
    },
    ///...
]
JavaScript

همانطور که مشاهده می‌کنید اعضا تیم‌های برحسب ID می‌باشند نه نام تیم.

پیاده سازی🔗

وظیفه اصلی شما این است که بر اساس اطلاعات دریافتی جدول امتیازات هر تیم را به صورت جداگانه پیاده‌سازی نماید.

استراکچر جدول امتیازات هر تیم به صورت زیر است:

<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>
HTML

همانطور که مشاهده کردید در اطلاعات دریافتی مقدار امتیاز ذکر نشده است و برای محاسبه امتیاز هر فرد باید از فرمول زیر استفاده نمایید:

score=kills×100+revives×75+assists×50 score = kills \times 100 + revives \times 75 + assists \times 50

برای محاسبه رتبه هر فرد در تیم خودش یا همان Rank کافی است افراد تیم را فقط و فقط بر حسب امتیازشان مرتب نمایید همچنین تضمین می‌شود امتیاز هیچ دو فردی برابر نخواهد بود.

همچنین تیم همکاران خیلی به اموجی‌ها علاقه دارد و معتقد است یکی از راه‌های کم هزینه و سریع برای زیباسازی وبسایت‌ها استفاده از اموجی است به همین جهت:

  • برای نمایش رتبه نفر اول به جای عدد از 🥇باید استفاده کنید.
  • برای نمایش رتبه نفر دوم به جای عدد از 🥈باید استفاده کنید.
  • برای نمایش رتبه نفر سوم به جای عدد از 🥉باید استفاده کنید.

در گام آخر شما باید درون div.status نام تیم برنده را نمایش دهید. تیمی برنده است که مجموع امتیازات کسب شده اعضای آن بیشتر باشد همچنین تضمین می‌شود امتیازات دو تیم برابر نخواهند بود.

آنچه باید آپلود کنید🔗

  • شما می‌توانید از فایل style.css که در بخش قبل تکمیل نمودید در اینجا استفاده کنید.
  • شما تنها مجاز به اعمال تغییرات در فایل index.js می‌باشید.
  • فایل مذکور به صورت خام یا فشرده .zip آپلود نمایید.

اتاق‌های خالی از اعتماد


ظاهر برنامه

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

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

شما تنها مجاز به انجام تغییرات در فایل‌های علامت زده می‌باشید

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                                                                            
Plain text
راه اندازی پروژه و سرور
  • فایل‌های پروژه اولیه را دانلود و از حالت فشرده خارج نمایید
  • سپس دستور زیر را برای نصب پکیج‌ها و وابستگی‌ها در پوشه پروژه درون ترمینال خود وارد نمایید: ‍‍
    cd initial && npm i
    
    Bash
- در نهایت برای راه اندازی سرور سوال دستور زیر را وارد نمایید:

```bash
cd server && npm i
node index.js
Plain text
نکات

هر قسمت سوال شامل دو بخش می‌باشد

منطق و پیاده سازی الگوریتم‌ها🔗

  • پیاده سازی مربوطه توابع و کلاس‌ها که امضای آن‌ها درون هر فایل به صورت مجزا قرار داده شده است.
  • شما موظف هستید که تابع را بر حسب خواسته آن بخش تکمیل نمایید.
  • رعایت کردن تایپ‌ها الزامی است!
  • تمامی توابع، متغیر‌ها و کلاس‌هایی که export شده‌اند و یا دارای متدهای عمومی (public) می‌باشند، توسط سیستم داوری بررسی و نمره دهی می‌شوند.

پیاده سازی رابط کاربری🔗

  • ساختاری کلی رابط کاربری از قبل با استفاده از کتابخانه tailwind پیاده شده است.
  • برای بعضی از بخش‌ها (مانند نمایش پیام) یک ساختار کلی برای شما تدارک دیده شده است و می‌توانید از آن استفاده نمایید.
  • در بخش‌هایی که شروط خطا ذکر شده است، باید پیغام خطا درون div#logs نمایش داده شوند.
  • پیاده سازی این بخش اجباری بوده و توسط سیستم داوری خودکار نمره دهی‌ می‌شود.

کتابخانه‌های مورد استفاده و مجاز در این تمرین🔗

در این سوال شما تنها مجاز به استفاده از کتابخانه‌های زیر می‌باشید:

مقدمه🔗

ماجرا از این قرار است که مهیار نه تنها به هیچ‌کس، حتی خودش اعتماد ندارد بلکه به نرم‌افزارها نیز اعتماد ندارد. به همین منظور، قصد دارد یک پیام‌رسان بسیار امن با رمزگذاری سرتاسری (End To End Encryption یه به اختصار E2EE) راه‌اندازی کند. در این پیامرسان پیام‌ها به صورت کاملا رمزگذاری شده به ازای هر فرد بین کاربران ارسال می‌شود.

از دیگر قابلیت‌های این پیامرسان امکان ایجاد گروه است! حتی چت‌های شخصی در قالب یک گروه صورت می‌گیرند، در این پیامرسان از گروه‌ها به عنوان اتاق (Room) یاد ‌می‌شود.

همچنین این پیامرسان هیچ اطلاعاتی را نه در سمت سرور و نه در سمت کاربر نگه داری نمی‌کند فلذا بدین معنا است که پس از بسته شدن مرورگر توسط کاربر تمامی اطلاعات فراموش‌شده و پس از بازگشت به برنامه باید اطلاعات مورد نیاز مجددا توسط کاربر وارد شوند.

معماری  برنامه

حافظه موقت🔗

به منظور مدیریت متغیرها به شیوه صحیح و با رعایت قید ذکر شده نیاز به پیاده سازی یک حافظه متغیر بسیار ساده “Key-Value Pair” وجود دارد که باید آن را درون فایل memory.ts تکمیل نمایید، این حافظه چیزی جز یکobjectساده نیست که چهار تابع برای مدیریت حافظه مذکور را دار می‌باشد:

  • تابع getMemory‍ که از حافظه موقت یک رونوشت (Copy) را برمیگرداند.
  • تابع memoryForget که با دریافت نام کلید آن را از حافظه موقت حذف می‌کند.
  • تابعmemoryRecall که با دریافت نام کلید مقدار تعیین شده برای آن کلید را بر می‌گرداند، در صورتی که کلید مذکور وجود نداشت باید مقدارundefined برگردانده شود.
  • تابع memoryRemember که با دریافت یک کلید و مقدار که می‌تواند یک متغیر باشد یا یک تابع که به عنوان ورودی مقدار متغیر قبلی را دریافت کرده و مقدار جدیدی را برمی‌گرداند، درون حافظه مقدار کلید را تنظیم و یا باز تنظیم کند.

اطلاعات کاربر🔗

  • برای این که کاربر بتواند از این برنامه طراحی شده استفاده کند باید اطلاعات زیر را درون مرورگر در قالب یک فایل .json با کلید‌های زیر بارگذاری نماید:
  1. نام کاربری که درون فیلدnameوارد می‌شود و از جنس رشته می‌باشد و باید حداقل ۳ کارکتر باشد در صورتی که طول رشته کمتر از ۳ بود باید ارور با پیغام زیر برگردانده شود:
"username" must be at least 3 characters
Plain text
  1. کلید عمومی (Public Key) که درون فیلد public در قالب یک رشته می‌باشد.
  2. کلید شخصی (Private Key) که درون فیلد‍private در قالب یک رشته می‌باشد.
  • در صورتی که کاربر هر یک از فیلدهای زیر را وارد نکرده بود باید اروری با پیغام زیر برگردانده شود:
You did not provide "<FIELD_NAME>"
Plain text
  • همچنین در مورد کلید‌های شخصی و عمومی این رشته کدگذاری شده باید موارد زیر بررسی و صحت سنجی شوند:

  • آیا کلید‌های ارسالی از نوع RSA256 می‌باشد؟ در غیر این صورت اروری با پیغام زیر برگردانده شود

Keys are not RSA256
Plain text
  • آیا کلیدها با یکدیگر همخوانی دارند؟ در صورت کلیدها با یکدیگر همخوانی نداشتند ارور با پیغام زیر برگردانده شود:
Invalid Key Pairs 
Plain text

مثال ورودی🔗

-برای مثال فایلی با محتوای زیر تمامی شرایط فوق را دارا می‌باشد:

{
  "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"
}
JSON

پیاده سازی🔗

برای تکمیل این قسمت شما باید موارد زیر را تکمیل نمایید

فایل encrypt.ts🔗

در این فایل شما باید isValidDataاز کلاس EncryptionService را تکمیل نمایید بدین نحو که با دریافت کردن اطلاعات کاربر در قالب یک Object ، خطاها را در صورت وجود در قالب یک آرایه شامل رشته‌ها برگرداند و درصورتی که هیچ مشکلی در داده ورودی نبود آرایه خالی برگرداند.

فایل main.ts🔗

در این فایل شما باید قابلیتی را پیاده سازی کنید در هنگامی که کاربر فایل جدید را در #file-upload بارگذاری کرد آن را صحت سنجی کرده و آن را درون حافظه با کلید credentials ذخیره نماید. و در صورت بروز خطا، خطاها را به کاربر نمایش دهد. همچنین در صورتی که فایل دارای مشکل بود باید پیغام زیر به کاربر نمایش داده شود:

File is Not Valid
Plain text

اتاق‌هایی برای گفت‌و‌گو🔗

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

ایجاد و عضویت🔗

همان‌طور که ذکر شد، کاربر برای ایجاد و یا عضویت در اتاق باید نام اتاق (roomName) به همراه گذرواژه (password) و کلید عمومی خود را در قالب یک شی به سمت سرور ارسال کند:

interface Request{
    roomName: string;
    password: string;
    publicKey: string;
}
TypeScript

مسیر /api/join/🔗

در گام اول، کاربر اطلاعات مذکور را به آدرس /api/join/ ارسال می‌کند و با یکی از سه سناریوی زیر مواجه می‌شود:

  1. در صورتی که کاربر اطلاعات را به درستی وارد کرده باشد ولی با خطای 404 مواجه شود، باید همان اطلاعات را به مسیر /api/create/ ارسال کند و پس از ایجاد، مجدداً درخواست اول تکرار و ارسال شود.

  2. در صورتی که گذرواژه به اشتباه وارد شده باشد، باید پیغامی با محتوای زیر در div#request-status نمایش داده شود:

Bad Credentials!
Plain text
  1. در صورتی که کاربر امکان دسترسی به گروه درخواست شده را نداشته باشد، در همان div#request-status پیغام زیر نمایش داده شود:
Unauthorized Access!
Plain text

مسیر /api/create/🔗

کاربر اطلاعات زیر را به آدرس /api/create/ ارسال می‌کند تا یک اتاق جدید ایجاد کند:


interface CreateRequest {
    groupName: string;
    password: string;
    publicKey: string;
}
TypeScript

اگر ایجاد اتاق موفقیت‌آمیز باشد، سرور یک پیام موفقیت با محتوای زیر به کاربر بازمی‌گرداند:

Room created successfully!
Plain text

در غیر این صورت، باید خطای دریافتی از سمت سرور درو div#request-status‍‍ نمایش داده شود.

مدیریت اتاق🔗

الزاما داشتن نام اتاق و گذرواژه آن راه مطلوبی برای تضمین امنیت گروه‌ها نیست زیرا در صورتی که اطلاعات حساس اتاق وصل شود هر فردی می‌تواند به این اتاق دسترسی پیدا کند به همین منظور مهیار تصمیم گرفت که برای مدیریت این قضیه قابلیتی اضافه کند تا افرادی که دارای صلاحیت هستند را با استفاده از کلید عمومی آن‌ها به گروه اضافه کند برای این منظور باید به درخواست زیر ارسال شود:

// PUT /api/room/
interface AddUserRequest {
    Request;
    user: string; // new user public key
}
Plain text
  • در صورتی که اتاق وجود نداشت باید خطایی با پیغام زیر برگردانده شود:
Room Not Found!
Plain text
  • از آنجایی که فقط فردی که گروه را ایجاد کرده می‌تواند افراد جدید را اضافه کند، در صورتی که کاربر، ایجاد کننده اتاق نباشد باید خطایی با پیغام زیر برگردانده شود:
Forbidden: Not the owner of the room
Plain text

پیاده سازی🔗

  • موارد خواسته شده در خصوص API ها و ارتباط با سرور را در فایل room.ts تکمیل نمایید
  • همچنین برای رابط کاربری فایل main.ts مطابق فیلدهایی که در فایل index.html عملکرد مطلوب را پیاده سازی کنید

اتصال به سوکت برای ارسال و دریافت پیام🔗

برای ارتباط بلادرنگ، کاربران باید به یک WebSocket متصل شوند که پیاده سازی آن در فایل socket.ts باید صورت بگیرد. برای این کار، باید از آدرس زیر استفاده شود و باید token حاصل شده از بخش قبلی را در بخش احراز هویت Header ارسال نماید:

/ws/room/<ROOM_NAME>/
Plain text

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

شیوه ارسال پیام🔗

  • در گام صفرم کاربر باید محتوای پیام خود را درون input مربوطه بنویسید و سپس دکمه Send را فشرده تا روند اصلی ارسال آغاز شود.
  • در گام اول باید به ازای تمامی کاربران موجود در اتاق (به غیر از خودتان) پیام ارسالی مورد نظر آن‌ها را با توجه به کلید عمومی هر کاربر رمزگزاری کنید.
  • در گام بعد جهت اینکه مشخص شود این پیام توسط شما ارسال شده است باید آن را با استفاده از کلید خود امضا کنید.
  • در گام بعدی با توجه به به پیام رمزنگاری شده برای دیگر کاربران باید آن را در قالب یک رخداد message پیام رمزگذاری شده را به همراه امضا در قالب یک شی به همراه شناسه کاربر مورد نظر ارسال نمایید.

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

  • پس از دریافت یک پیام در گام اول باید این امر صحت سنجی شود که با توجه به اطلاعات دریافتی (پیام رمزگذاری شده و امضای مذکور) آیا این پیام واقعا از آن کاربر آمده است یا خیر؟ در غیر این صورت اروری تحت عنوان زیر نمایش داده شود
    Message verification failed for sender <SENDER_USERNAME>
    Plain text
  • در گام بعد باید پیام دریافت شده باید با توجه به کلید شخصی کاربری که پیام را دریافت کرده است رمزگشایی شده و بازگردانده شود.