**برای این سوال، نسخهی داتنت شما باید ۷ باشد.**
----------
![اندیس](https://quera.org/qbox/view/7PlWCxxoTi/D.png)
شما به قبل سال `2000` برگشتهاید، زمانی که فناوری دیتابیسها به تازگی در حال ظهور است و مهندسان در تلاشند تا راهحلهای نوآورانهای برای جستجوی اطلاعات پیدا کنند. بسیاری از آنها از ایدههای جدید شگفتزده شده و دنیای فناوری اطلاعات در آستانهی تغییرات شگرفی است.
شما که از آینده خبر دارید، تصمیم گرفتهاید سیستم ابتدایی `Full-Text Search` را پیادهسازی کنید. با این اختراع، شما نه تنها دنیای جستجو را متحول میکنید بلکه تاریخ را نیز تحت تأثیر قرار خواهید داد و این اختراع را به نام خود ثبت خواهید کرد.
# جزئیات پروژه
پروژهی اولیه را از [این لینک](/problemset/assignments/4367/download_problem_initial_project/253396/) دانلود کنید. ساختار فایلهای پروژه بهصورت زیر است:
```cs
└── SearchEngine
├── Document.cs
├── Index.cs
├── Program.cs
├── Query.cs
└── SearchEngine.csproj
```
شما باید سه کلاس `Document`، `Index` و `Query` را مطابق با مواردی که در ادامه مطرح میشود، کامل کنید.
## کلاس `Document`
اولین کلاسی که باید تکمیل کنید کلاس `Document` است. این کلاس بدنه اصلی داکیومنتهای شما را برای اندیس مشخص میکند و باید شامل ویژگیهای(property) زیر باشد:
| نام | نوع |
|:----------:|:------------------:|
| Id | `long` |
| Text | `string` |
| Date | `DateTime` |
## کلاس `Query`
این کلاس شامل ویژگیهای کوئری است که قصد دارید طبق این ویژگیها داکیومنتهایی را از درون اندیس بازیابی کنید. این کلاس شامل ویژگیهای زیر میشود:
| نام | نوع |
|:----------:|:------------------:|
| Text | `string` |
| Date | `DateTime` |
| EndDate | `DateTime` |
## کلاس `Index`
این کلاس اصلیترین کلاسی است که باید پیادهسازی کنید. این کلاس شامل داکیومنتها و اندیسها میشود. اندیسهای این کلاس در واقعا [اندیسهای معکوس](https://en.wikipedia.org/wiki/Inverted_index) (Inverted index) به هر داکیومنت هستند.
```cs Index.cs
namespace SearchEngine;
public class Index
{
private List<Document> documents = new();
private Dictionary<string, HashSet<long>> textIndex = new();
private SortedDictionary<DateOnly, HashSet<long>> dateIndex = new();
public Index() { }
public Index(string filePath)
{
throw new NotImplementedException();
}
public void IndexDocument(Document document)
{
throw new NotImplementedException();
}
public void SaveIndexToFile(string filePath)
{
throw new NotImplementedException();
}
public List<Document> Search(Query query)
{
throw new NotImplementedException();
}
}
```
همانطور که میبینید، دو اندیس `textIndex` و `dateIndex` وجود دارند که نحوه ساخت این اندیسها در ادامه آورده شده است. مطابق این فایل، شما در این کلاس باید یک کانستراکتور و سه متد که در ادامه جزئیات آنها ذکر میشود را پیادهسازی نمایید:
کانستراکتور `Index`: این کانستراکتور فایلی که در مسیر ورودی دریافت کرده را به صورت متن خوانده و اندیسهای گفته شده را باید به درستی مقداردهی کند.
متد `saveIndexToFile`: این متد یک مسیر را دریافت و کل کلاس `Index` را با تمام مقادیرش به صورت متن در این مسیر ذخیره میکند.
متد `indexDocument`: این متد یک داکیومنت را دریافت میکند و اندیسهای گفته شده را به صورت زیر ایجاد میکند:
+ برای ساخت `textIndex` باید ویژگی `text` هر داکیومنت براساس کاراکترهای غیر کلمهای (حرف، رقم یا `_`) شکسته شود و داکیومنتها اندیس شوند.
+ برای ساخت `dateIndex` هر داکیومنت براساس ویژگی `date` خودش اندیس میشود.
متد `search`: این متد وظیفه دارد تا داکیومنتهایی را براساس کوئری ورودی برگرداند. هر کدام از ویژگیهای کلاس `Query` میتواند نال باشند ولی در صورتی که هر کدام از مقادیر نال نبود باید داکیومنتهایی براساس اولویت زیر برگردانده شوند:
1. متن
2. بازه زمانی (این به این معنی است که اگر در کوئری بازه زمانی وارد شده بود، این بازه اولویت بیشتری دارد)
3. زمان دقیق
# مثال
مثالهایی به صورت تست نمونه در اختیار شما قرار داده شده است که میتوانید از آنها کمک بگیرید. به عنوان مثال به مورد زیر دقت کنید:
```cs
Index index = new Index();
index.IndexDocument(new Document(1, "Quera online coding contests", DateTime.Now));
index.IndexDocument(new Document(2, "Quera for programmers", DateTime.Now.AddDays(-4)));
index.IndexDocument(new Document(3, "Practice coding skills", DateTime.Now.AddMonths(-11)));
Query query = new Query("Quera", null, null);
List<Document> result = index.Search(query);
```
خروجی مثال بالا باید داکیومنتها با آیدی `1`و `2` را برگرداند.
# نکات
+ دو کلاس `Document` و `Query` باید شامل کانستراکتوری با همه ویژگیها باشند.
+ **تضمین میشود** داکیومنت با آیدی تکراری وارد نخواهد شد.
+ **دقت کنید** که ساختار ابتدایی کلاسها را تغییر ندهید.
+ **دقت کنید** که کلاسهای شما در صورت لزوم باید قابلیت سریالایز و دسریالایز شدن داشته باشند.
# آنچه باید آپلود کنید
پس از پیادهسازی موارد خواستهشده، فقط این سه کلاس را زیپ کرده و آپلود کنید.
```cs
[your-solution-file].zip
└── SearchEngine
├── Document.cs
├── Index.cs
├── Program.cs
├── Query.cs
└── SearchEngine.csproj
```