*سلیب* که از امنیت کوئرا به ستوه آمده بود، با *نیما* (اسطورهی امنیت در سطح بینالمللی) در اینباره صحبتی را شروع کرد. *نیما* به این نتیجه رسید که کوئرا نیاز به یک اقدام امنیتی در ورود به حساب کاربری دارد. پیشنهاد او تأیید از طریق *SMS* بود و تأکید اکیدی بر زمان انقضای آنها داشت. به نظر او هر کد تأیید باید فقط برای ۱۰ ثانیه معتبر میبودند و پس از گذشت بیش از ۱۰ ثانیه، کد دیگر مورد قبول نباشد. *سلیب* از آنسو تاکید بر ماندگاری دیتاها داشت. به نظر او نیاز بود تا تمامی اطلاعات را به فرمت زیر در یک فایل *CSV* نگهداری کند:
```csv sample-data.csv csv
Phone,Code,Expiration
```
در ستون اول شماره مورد نظر، ستون دوم کد ساخته شده برای شماره و در ستون سوم اعتبار کد را نمایش میدهد، در ادامه به بیان جزئیات بیشتر سؤال میپردازیم.
# جزئیات پروژه
پروژهی اولیه را از [این لینک](/problemset/assignments/4367/download_problem_initial_project/169492/) دانلود کنید.
ساختار فایلهای پروژه بهصورت زیر است:
```
SMSAuthentication
├── pom.xml
├── src
│ ├── main
│ │ └── java
│ │ └── org
│ │ └── quera
│ │ └── smsauthentication
│ │ └── <mark class="red" title="شما تنها مجاز به تغیر این فایل هستید.">SMSAuthentication.java</mark>
│ └── test
│ └── java
│ └── org
│ └── quera
│ └── smsauthentication
│ └── SMSAuthenticationSampleTest.java
└── test.csv
```
شما باید متدهای `generateCode`، `sendAuthenticationSMS`، `loadData`، `verifyCode` موجود در کلاس `SMSAuthentication` را مطابق با خواستههای سؤال پیادهسازی کنید. نمای کلی فایل مورد نظر به شکل زیر است:
```java SMSAuthentication.java java
package org.quera.smsauthentication;
import ...
public class SMSAuthentication {
public static String generateCode() {
// TODO: Implement
}
public static String sendAuthenticationSMS(String phone, String path) {
// TODO: Implement
}
public static List<String[]> loadData(String path) {
// TODO: Implement
}
public static boolean verifyCode(String code, String phone, String path) {
// TODO: Implement
}
public static void main(String[] args) {
System.out.println(sendAuthenticationSMS("09381358888", "test.csv"));
Scanner sc = new Scanner(System.in);
String code = sc.next();
System.out.println(verifyCode(code,"09381358888","test.csv"));
}
}
```
## متد `generateCode`
این متد باید یک رشته تصادفی به **طول ۵** بسازد و مقدار آن را برگرداند. در این رشته میتوانید از **فقط متشکل از ارقام انگلیسی** استفاده کنید. نمونهی اجرای متد در زیر آمده است:
```java Terminal terminal
>>> generateCode()
40142
>>> generateCode()
18272
>>> generateCode()
00168
```
## متد `sendAuthenticationSMS`
این متد یک رشته به عنوان شماره و رشتهای دیگر به عنوان آدرس فایلی که باید اطلاعات را در آن ذخیره کند، به عنوان ورودی دریافت میکند. خروجی این متد باید رشتهای به فرمت `JSON` باشد. در خروجی `JSON` مورد نظر باید کلید و مقدارهای زیر را داشته باشد:
* کلید `phone` برابر با مقدار شماره مورد نظر خواهد بود.
* کلید `code` برابر با کد ساخته شده برای شماره مورد نظر خواهد بود.
* کلید `exp` برابر با زمانی که کد مورد نظر منقضی میشود است، زمان در این سؤال به فرمت `"yyyy/MM/dd-HH:mm:ss"` استفاده میشود.
این متد باید این محتوا را درون فایل *CSV* موجود در آدرس `path` ذخیره کند. خروجی و رفتار خواسته شده در بخش مثال با جزئیات بیشتری نمایش داده شده است.
### مثال
```java Terminal terminal
>>> sendAuthenticationSMS("09381354444", "test.csv")
{"phone":"09381354444","code":"06505","exp":"2022/10/04-18:02:15"}
>>> sendAuthenticationSMS("09381354443", "test.csv")
{"phone":"09381354443","code":"26052","exp":"2022/10/04-18:07:39"}
>>> sendAuthenticationSMS("09381354444", "test.csv") // duplicate
{"phone":"09381354444","code":"00300","exp":"2022/10/04-19:02:48"}
```
محتوای چند خط آخر فایل `test.csv` پس از اجرای بالا برابر با زیر خواهد بود:
```csv test.csv csv
Phone,Code,Expiration
<mark class="red" title="محتواهای قبلی موجود در فایل">...</mark>
09381354444,06505,2022/10/04-18:02:15
09381354443,26052,2022/10/04-18:07:39
09381354444,00300,2022/10/04-19:02:48
```
## متد `loadData`
این متد یک رشته به عنوان آدرس فایلی که باید اطلاعات آن را بخواند، به عنوان ورودی دریافت میکند. خروجی این متد لیستی از آرایهای از `String`ها خواهد بود که برابر با مقادیر موجود در فایل *CSV* ورودی متد است.
### مثال
برای مثال فرض کنید محتوای فایل *CSV* بهصورت زیر باشد:
```csv test.csv csv
Phone,Code,Expiration
09381354444,06505,2022/10/04-18:02:15
09381354443,26052,2022/10/04-18:07:39
09381354444,00300,2022/10/04-19:02:48
```
اگر متد را بهصورت زیر فراخوانی کنیم
```java snippet java
List<String[]> allData = loadData("test.csv");
```
و بخواهیم خروجی متد را بهصورت زیر چاپ کنیم:
```java snippet java
for(String[] data : allData) {
for(String attr : data) {
System.out.print(attr + " ");
}
System.out.println();
}
```
خروجی بهصورت زیر خواهد بود
```
09381354444 06505 2022/10/04-18:02:15
09381354443 26052 2022/10/04-18:07:39
09381354444 00300 2022/10/04-19:02:48
```
**دقت کنید که خط اول** (یا همان `Phone,Code,Expiration`) **در خروجی متد وجود ندارد**.
## متد `verifyCode`
این متد یک رشته به عنوان کد، یک رشته به عنوان شماره و رشتهای دیگر به عنوان آدرس فایلی که باید اطلاعات را از آن بخواند، به عنوان ورودی دریافت میکند. خروجی این متد یک `boolean` است که در صورتی که کد با شماره مورد نظر تطابق داشت و **کد منقضی نشده بود،** باید مقدار `true` برگرداند و در غیر این صورت مقدار `false` برگرداند.
# نکات
+ شما در این سؤال مجاز به تغییر فایل `pom.xml` نیستید.
+ برای کار با `JSON`، تنها مجاز به استفاده از کتابخانه `opencsv` هستید.
+ برای کار با *CSV* ، تنها مجاز به استفاده از کتابخانه `jackson-databind` هستید.
+ به جز کتابخانههای موجود در `pom.xml`، تنها مجاز به استفاده از کتابخانههای استاندارد جاوا هستید.
+ هر کد تنها **ده ثانیه** زمان دارد.
+ **دقت کنید** که تاریخ و زمان انقضای کد را باید دقیقا برابر با ۱۰ ثانیه پس از تولید کد (یا فراخوانی متد `sendAuthenticationSMS`) قرار دهید.
+ شما مجاز به عوض کردن فرمت ذخیرهسازی اطلاعات در فایل *CSV* نیستید و باید دقیقا برابر با فرمت خواسته شده، اطلاعات را ذخیره سازی کنید.
+ داوری این سؤال، بیشتر از باقی مسائل طول میکشد.
# آنچه باید آپلود کنید
پس از پیادهسازی موارد خواستهشده، فایل تمامی پروژه را زیپ کنید و آن را آپلود کنید. فایل زیپ شما باید بهصورتی باشد که پس از خروج از حالت فشرده، پوشهی `src` مشاهده شود.