*سلیب* و *افض* به یک مشکل مشترک رسیدند. آنها تصمیم گرفتند تا از شرّ سرچ هرساله خود راحت شوند. هر دوی آنها همیشه فراموش میکردند که جام جهانی بعدی در چه سالی برگزار میشود و همواره یکی از دو عبارت زیر را سرچ میکردند:
> جام جهانی بعدی کی است
و یا
> when is the next world cup
ناگهان *سلیب* فکری به سرش زد، زمان آن رسیده بود تا یکبار برای همیشه برنامهای به زبان جاوا بنویسند که با ورودی گرفتن سال فعلی، سال جام جهانی بعدی را به آنها بگوید. به نظر *سلیب* اجرا کردن یک برنامه جاوا به شدت آسانتر از سرچ کردن با چالشهای سخت و طولانی همچون تایپ کردن، کندی اینترنت، فیلترینگ گوگل و... بود، البته که همگی با *سلیب* موافقیم اما مشکل آنجا بود که *سلیب* نمیتوانست برنامه مورد نظر را پیادهسازی کند برای همین از شما کمک میخواهد تا به او در این راه کمک کنید.
# جزئیات پروژه
پروژهی اولیه را از [این لینک](/contest/assignments/45415/download_problem_initial_project/157737/) دانلود کنید.
ساختار فایلهای پروژه بهصورت زیر است:
```
WorldCup
├── Predictor.java
└── test
└── PredictorSampleTest.java
```
شما باید تابع `predict` موجود در فایل `Predictor.java` را مطابق با خواست مسئله پیادهسازی کنید. امضای تابع مورد نظر به شکل زیر است:
```java Predictor.java java
public class Predictor {
public static int predict(int year) {
// TODO: Implement
}
public static void main(String[] args) {
System.out.println(predict(2021)); // 2022
System.out.println(predict(2022)); // 2022
System.out.println(predict(2023)); // 2026
}
}
```
این تابع یک متغیر عددی با نام `year` به عنوان سال فعلی ورودی میپذیرد. شما باید بگویید جام جهانی بعدی در چه سالی برگزار میشود. **توجه داشته باشید که جام جهانی تنها در سالهایی برگزار میشود که باقی مانده عدد سال بر عدد ۴ برابر با عدد ۲ باشد.**
# مثال
```java Terminal terminal
System.out.println(predict(2021)); // 2022
System.out.println(predict(2022)); // 2022
System.out.println(predict(2023)); // 2026
```
# نکات
+ توجه داشته باشید که جام جهانی تنها در سالهایی برگزار میشود که باقی مانده **عدد سال** بر **عدد ۴** برابر با **عدد ۲** باشد.
+ مقدار خواسته شده مسئله را برگردانید و آن را **پرینت نکنید**.
+ در این مسئله تنها مجاز به استفاده از کتابخانههای استاندارد جاوا هستید.
# آنچه باید آپلود کنید
پس از پیادهسازی موارد خواستهشده، فایل `Predictor.java` را آپلود کنید.
امیرحسین که فردی است جوان و جویای نام! بهدنبال پیادهسازی سیستمی است که دنیا را تکان دهد. او فکری در سر دارد که احساس میکند اولین قدم از رسیدن به یک سیستم هوشمند قوی است.
او قصد دارد کلاسهایی را در زبان جاوا، فقط با داشتن اطلاعات کلی از آن کلاسها و بهصورت پویا ایجاد کند. امیرحسین که اولین گامهای این پروژه را نوشته، در تکمیل آن از شما کمک خواسته است.
# جزئیات پروژه
پروژهی اولیه را از [این لینک](/contest/assignments/45415/download_problem_initial_project/157739/) دانلود کنید. ساختار فایلهای پروژه اولیه بهصورت زیر است:
```
.
├── ClassDetail
├── ClassTypes
├── ClassUtil
├── Method
└── OopType
```
وظیفه اصلی شما در این سوال، تکمیل کلاس `ClassUtil` است. در این کلاس متدی با نام `classMaker` وجود دارد که پارامتر ورودی از نوع `ClassDetail` دریافت میکند و باید کلاسی با اطلاعاتی که از این پارامتر دریافت میکند، بسازد. در ادامه به بررسی کلاس `ClassDetail` میپردازیم:
### کلاس `ClassDetail`
این کلاس دارای ۵ پراپرتی زیر است:
1. پراپرتی `type`: این پراپرتی که از نوع `OopType` است مشخص کننده نوع کلاسی است که باید ساخته شود. این نوع میتواند `enum`، `interface` یا `class`باشد.
2. پراپرتی `name`: این پراپرتی که از نوع رشته است نام کلاس را مشخص میکند.
3. پراپرتی `properties`: این پراپرتی که از نوع `Map` است نوع و نام پراپرتیهای کلاس را مشخص میکند، در این مپ کلیدها نوع و مقادیر نام پراپرتیها است.
4. پراپرتی `methods`: این پراپرتی لیستی از کلاس `Method` است. کلاس `Method` نیز دارای سه پراپرتی `returnType`، `name` و `parameters` است که بهترتیب نام، نوع مقدار بازگشت و پارامترهای ورودی متد را مشخص میکند.
5. پراپرتی `oop`: این پراپرتی لیستی از رشتهها را مشخص میکند. این رشتهها نام کلاسهای جاواست که شما باید براساس نوع این کلاسها، آنها را `extends` یا `implements`کنید.
### کلاس `ClassUtil`
حال که با کلاس `ClassDetail` آشنا شدید باید کلاس `ClassUtil` را تکمیل کنید. در ادامه به بررسی دو مثال از عملکرد این کلاس خواهیم پرداخت.
فرض کنید قصد داریم تا یک `enum` با نام `Month` بسازیم که پراپرتی با نام `NAME` دارد. برای این کار کد زیر را مینویسیم و از متد کلاسی که تکمیل کردید استفاده میکنیم:
```java Main.java java
OopType type = OopType.ENUM;
String name = "Month";
Map<String, String> properties = Map.of("", "NAME");
String code = ClassUtil.classMaker(new ClassDetail(type, name, properties, List.of(), List.of()));
```
خروجی این کد باید کلاسی بهصورت زیر باشد:
```java Month.java java
public enum Month {
NAME;
}
```
در مثالی دیگر فرض کنید قصد داریم تا کلاسی بسازیم که دارای مقادیری بهصورت زیر باشد:
```java Main.java java
OopType type = OopType.CLASS;
String name = "Month";
Map<String, String> properties = Map.of("String", "name");
List<String> oop = List.of("Object");
String code = ClassUtil.classMaker(new ClassDetail(type, name, properties, List.of(), oop));
```
که در این حالت متغیر `code` باید بهصورت زیر باشد:
```java Month.java java
import java.lang.Object;
import java.lang.String;
public class Month extends Object {
String name;
}
```
# نکات
+ کلاس شما حتما باید بدون مشکل کامپایل شود.
+ تضمین میشود نام کلاسهایی که در پراپرتی `oop` قرار داده میشود، حتما وجود دارند و از پکیجهای استاندارد جاوا هستند.
+ کلاسی که میسازید **نباید** هیچ کلاس اضافی را `import` کرده باشد.
+ رعایت تمام موارد شیگرایی، بهعنوان مثال هر کلاس فقط میتواند یک کلاس را `extends` و ... ، باید در کلاس شما رعایت شده باشد.
+ در صورت وجود مشکل در قسمت `extends` یا `implements` ، کلاس شما باید کامل ساخته شود و فقط `extends` یا `implements` را نادیده بگیرد.
+ اگر کلاسی متد داشت، بدنه متدها باید خالی باشد و تضمین میشود نوع خروجی متدها `void` باشد.
# آنچه باید آپلود کنید
پس از پیادهسازی موارد خواستهشده، کلاس `ClassUtil` را زیپ کرده و ارسال کنید.
![تزریق خودکار](https://quera.org/qbox/view/TUr0D912sk/dependency-injection.jpg)
*ابوالفضل* مدت زیادی است که با فریمورک *Spring Boot* کار میکند. اخیراً او به این فکر فرو رفته که قابلیتهای مختلف این فریمورک چگونه کار میکنند. برای درک عمیقتر این موضوع، او میخواهد بداند قابلیت *autowiring* که تزریق وابستگی (*dependency injection*) خودکار با استفاده از آن انجام میشود چگونه کار میکند. از شما میخواهیم نسخهی سادهای از این بخش فریمورک *Spring Boot* را برای او بنویسید.
# جزئیات پروژه
پروژهی اولیه را از [این لینک](/contest/assignments/45415/download_problem_initial_project/157736/) دانلود کنید. ساختار فایلهای پروژه بهصورت زیر است:
```
dependency-injection
├── annotations
│ ├── Autowired.java
│ ├── Component.java
│ └── Qualifier.java
├── exceptions
│ ├── CircularDependencyFoundException.java
│ ├── NoPublicConstructorFoundException.java
│ ├── NoUniqueComponentFoundException.java
│ └── NoUniqueConstructorFoundException.java
├── test
│ ├── A1.java
│ ├── B1.java
│ ├── IA.java
│ └── IB.java
├── Injector.java
└── Main.java
```
## انوتیشن `@Component`
از این انوتیشن در کلاسهایی استفاده میشود که بخواهیم امکان استفاده از آنها در تزریق وابستگی خودکار فراهم باشد. این انوتیشن شامل پارامتر `value` از نوع `String` است.
## انوتیشن `@Autowired`
از این انوتیشن زمانی استفاده میشود که بخواهیم کانستراکتور موردنظر را جهت فراخوانی هنگام تزریق وابستگی خودکار مشخص کنیم. اگر کلاس موردنظر تنها شامل یک کانستراکتور باشد، نیازی به استفاده از این انوتیشن نیست. در غیر اینصورت، فقط یکی از کانستراکتورهای کلاس باید دارای این انوتیشن باشد.
## انوتیشن `@Qualifier`
از این انوتیشن زمانی استفاده میشود که بخواهیم از بین چند پیادهسازی برای یک اینترفیس یا کلاس، یکی را برای *autowiring* انتخاب کنیم. این انوتیشن شامل پارامتر `value` از نوع `String` است.
## کلاس `Injector`
این کلاس، وظیفهی اصلی قابلیت *autowiring* را برعهده دارد. این کلاس شامل متدی با نام `get` و با امضای زیر است:
```java
public static <T> T get(Class<T> typeClass)
```
این متد را بهگونهای پیادهسازی کنید که با دادن یک کلاس به آن، یک نمونه از آن کلاس ساخته شود. همچنین، کلاس دادهشده میتواند شامل یک یا چند کانستراکتور باشد.
نکات زیر هنگام پیادهسازی متد `get` باید رعایت شوند:
+ اگر کلاس موردنظر شامل کانستراکتور `public` نبود، یک استثنا از نوع `NoPublicConstructorFoundException` پرتاب کنید.
+ اگر کلاس موردنظر دارای بیش از یک کانستراکتور بود و بیش از یکی از این کانستراکتورها دارای انوتیشن `@Autowired` بودند، یک استثنا از نوع `NoUniqueConstructorFoundException` پرتاب کنید.
+ اگر بیش از یک پیادهسازی برای یک اینترفیس یا کلاس جهت ساخت آبجکت وجود داشت که هیچکدام از آنها دارای انوتیشن `@Qualifier` نبودند، یک استثنا از نوع `NoUniqueComponentFoundException` پرتاب کنید (برای مثال، اگر اینترفیسی با نام `IA` داشته باشیم و دو پیادهسازی `A1` و `A2` از آن داشته باشیم که مقدار موجود در `@Component` آنها یکسان باشد).
+ اگر یک `@Component` با `value` یکسان برای بیش از یک پیادهسازی برای یک اینترفیس یا کلاس وجود داشت، یک استثنا از نوع `NoUniqueComponentFoundException` پرتاب کنید.
+ اگر هنگام ساخت آبجکتها با وابستگی چرخشی مواجه شدید (مثلاً اگر کلاس `A` در کانستراکتور خود یک آبجکت از نوع `B` لازم داشته باشد و کلاس `B` در کانستراکتور خود یک آبجکت از نوع `A` لازم داشته باشد)، یک استثنا از نوع `CircularDependencyFoundException` پرتاب کنید.
# نکات
+ بررسی خطاها و پرتاب استثناها باید هنگام فراخوانی متد `get` کلاس `Injector` و هنگام بررسی آبجکتهای موردنظر جهت ساخت صورت گیرد.
+ در صورت نیاز، میتوانید متدهای دیگری نیز در کلاس `Injector` تعریف کنید.
+ **تضمین میشود** که از نوع دادههای *generic* بهعنوان آرگومان متد `get` کلاس `Injector` استفاده نمیشود.
# آنچه باید آپلود کنید
پس از پیادهسازی متد `get`، فایل `Injector.java` را آپلود کنید.
شهرام و بهرام بعد از تصادف سنگینی که منجر به خسارت بسیار سنگینی که برای آنها شد تصمیم گرفتند تا شرکت بیمهای را تاسیس کنند. این دو با شرکتهای مختلف بیمه وارد مذاکره شدند و قول همکاری با آنها را گرفتهاند.
این دو قصد دارند برای شروع *API*هایی را طراحی و در معرض استفاده عموم قرار دهند اما از آنجا که این دو نفر هیچ تجربهای در زمینه برنامهنویسی ندارند، برای این کار از شما کمک خواستهاند.
نیازمندیهای این دو برای این پروژه عبارت است از:
1. تعریف شرکت بیمه
2. تعریف انواع بیمه توسط یک شرکت خاص
3. دریافت اطلاعات شرکت بیمه
4. دریافت اطلاعات بیمه
مطابق با این نیازمندیها، وبسرویسهای زیر باید پیادهسازی شوند:
| عنوان | آدرس |
|:---------------------:|:----------------------: |
| تعریف شرکت بیمه | POST /companies/save |
| تعریف انواع بیمه توسط یک شرکت خاص | POST /insurances/save |
| دریافت اطلاعات شرکت بیمه | GET /companies/get/{id} |
| دریافت اطلاعات بیمه | GET /insurances/get/{id} |
# جزئیات پروژه
ابتدا پروژهی اولیه و خام اسپرینگ بوتی را از [این لینک](/contest/assignments/45415/download_problem_initial_project/157740/) دانلود کنید. سپس شما باید به پیادهسازی نیازمندیهای ذکر شده بپردازید.
### تعریف شرکت بیمه
در برنامه شما باید بتوان شرکت جدیدی ثبت کرد. شرکتها باید در جدولی به نام `companies` ذخیره شوند و اطلاعات این جدول بهصورت زیر است:
| نام ستون | نوع |
|:----------:|:------------------:|
| name | String |
همچنین این شرکت میتواند **چندین** بیمه *(insurances)* ایجاد کند.
برای ایجاد شرکت بیمه شما باید اندپوینتی با اطلاعات زیر ایجاد کنید:
```json
URL:
"POST /companies/save"
Request:
content-type: "application/json"
{
"name": "shahram"
}
```
اگر شرکت ذخیره شد باید عبارت `Company saved.` و اگر هر خطایی رخ داد، عبارت `Company saving problem!` را با وضعیت `BAD_REQUEST` برگردانید.
### تعریف انواع بیمه توسط یک شرکت خاص
در برنامه شما باید بتوان برای هر شرکت تعدادی بیمه ثبت کرد. برای شروع برنامه شما باید از دو نوع بیمه افراد و وسایل نقلیه پشتیبانی کند. بیمهها باید در جدولی به نام `insurances` ذخیره شوند و اطلاعات این جدول بهصورت زیر است:
| نام ستون | نوع |
|:----------:|:------------------:|
| type | ENUM |
| name | String |
| price | Double |
| created_at | LocalDateTime |
همچنین این جدول به **شرکتی** *(company)* که آن را ایجاد کرده، مرتبط است و ستون `created_at` زمان درج ردیف را نگه میدارد و `type` هم *ENUM* ای است که میتواند `PERSON` یا `VEHICLE` باشد.
جدولهای `vehicles_insurance` و `persons_insurance` نیز باید در پروژه شما وجود داشته باشند که اطلاعات تکمیلی بیمهها را در خود نگه میدارند تا اگر شرکتی این نوع بیمهها را ثبت کرد، اطلاعات تکمیلی در این جداول ذخیره شود.
ساختار جدول `vehicles_insurance`:
| نام ستون | نوع |
|:----------:|:------------------:|
| usage | String |
ساختار جدول `persons_insurance`:
| نام ستون | نوع |
|:----------:|:------------------:|
| min_age | int |
برای ایجاد بیمهها شما باید اندپوینتی با اطلاعات زیر ایجاد کنید:
```json
URL:
"POST /insurances/save"
Request:
content-type: "application/json"
{
"type": "PERSON",
"name": "shakhs",
"price": 300000,
"company_id": 1,
"minAge": 20
}
```
اگر بیمه ذخیره شد باید عبارت `Insurance saved.` و اگر هر خطایی رخ داد، عبارت `Insurance saving problem!` را با وضعیت `BAD_REQUEST` برگردانید.
همانطور که میبینید در مثال بالا بیمه افراد با نام دلخواه برای یک شرکت ایجاد میشود. حال فرض کنید قصد دارد تا بیمه وسایل نقلیه را نیز برای این شرکت ایجاد کنیم، برای این کار همین اندپوینت را با اطلاعات زیر صدا میزنیم:
```json
{
"type": "VEHICLE",
"name": "mashin",
"price": 220000,
"company_id": 1,
"usage": "for car"
}
```
بنابراین باید اندپوینت و جداول شما برای انواع بیمهها بهخوبی پیادهسازی شوند.
### دریافت اطلاعات شرکت بیمه
برای این قسمت اندپوینتی ایجاد کنید تا بتوان اطلاعات یک شرکت بیمه خاص را دریافت کرد، اطلاعات این اندپوینت باید بهصورت زیر باشد:
```json
URL:
"POST /companies/get/{id}"
Response:
{
"name": "shahram",
"insurances": [
{
"type": "PERSON",
"name": "shakhs",
"price": 200000,
"company_id": 1,
"minAge": 20
},
{
"type": "VEHICLE",
"name": "mashin",
"price": 220000,
"company_id": 1,
"usage": "for car"
}
]
}
```
### دریافت اطلاعات بیمه
برای این قسمت اندپوینتی ایجاد کنید تا بتوان اطلاعات یک بیمه خاص را دریافت کرد، اطلاعات این اندپوینت باید بهصورت زیر باشد:
```json
URL:
"POST /insurances/get/{id}"
Response:
{
"type": "PERSON",
"name": "shakhs",
"price": 200000,
"company_id": 1,
"minAge": 20
}
```
# نکات
+ برای این پروژه از دیتابیس `h2` استفاده شده است.
+ شما مجاز به ایجاد هر کلاسی در مسیر `org/quera/bime` هستید، فقط باید پروژه شما خواستههای مسئله را بهخوبی پیادهسازی کرده باشد.
# آنچه باید آپلود کنید
پس از پیادهسازی موارد خواستهشده، این پروژه را زیپ کرده و ارسال کنید.
در این سؤال، باید سامانهی فروش بلیت مسابقات فوتبال در استادیومهای مختلف را پیادهسازی کنید!
# جزئیات پروژه
پروژهی اولیه را از [این لینک](/contest/assignments/45415/download_problem_initial_project/157738/) دانلود کنید.
+ این پروژه از *Maven* استفاده میکند و وابستگیها در *POM* تعریف شدهاند. امکان تغییر این وابستگیها وجود ندارد.
+ برای اجرای تستها، از دیتابیس *[H2](https://www.h2database.com/)* استفاده میشود.
+ در این پروژه، وابستگی *[Project Lombok](https://projectlombok.org/)* تعریف شده و قابل استفاده است.
+ بستهی `org.quera.ticket` شامل موجودیتهای *JPA* برنامه است که مطابق با *schema* دیتابیس طراحی شدهاند. شناسه (`id`) موجودیتها بهصورت خودکار توسط *Hibernate* تولید میشود.
+ بستهی `org.quera.ticket.security` شامل کلاسهایی برای مدیریت احراز هویت است.
## سرویسها
تعدادی وبسرویس *REST* مطابق نیازمندیهای زیر باید پیادهسازی شود:
| آدرس | عنوان |
| :------------------------ | ----------------------: |
| `GET /api/ping` | بررسی صحت برنامه |
| `POST /api/users/{id}/update_balance` | تغییر موجودی یک کاربر |
| `GET /api/stadiums` | دریافت اطلاعات استادیومها |
| `POST /api/stadiums` | ایجاد استادیوم جدید |
| `GET /api/stadiums/{id}` | دریافت اطلاعات یک استادیوم |
| `DELETE /api/stadiums/{id}` | حذف یک استادیوم |
| `GET /api/teams` | دریافت اطلاعات تیمها |
| `POST /api/teams` | ایجاد تیم جدید |
| `GET /api/teams/{id}` | دریافت اطلاعات یک تیم |
| `DELETE /api/teams/{id}` | حذف یک تیم |
| `GET /api/matches` | دریافت اطلاعات مسابقات |
| `POST /api/matches` | ایجاد مسابقهی جدید |
| `GET /api/matches/{id}` | دریافت اطلاعات یک مسابقه |
| `DELETE /api/matches/{id}` | حذف یک مسابقه |
| `GET /api/seat_classes` | دریافت اطلاعات مجموعه جایگاهها |
| `POST /api/seat_classes` | ایجاد مجموعه جایگاه جدید |
| `GET /api/seat_classes/{id}` | دریافت اطلاعات یک مجموعه جایگاه |
| `DELETE /api/seat_classes/{id}` | حذف یک مجموعه جایگاه |
| `GET /api/tickets` | دریافت لیست بلیتهای کاربر فعلی |
| `POST /api/tickets` | خرید بلیت برای یک صندلی |
### بررسی صحت برنامه
با ارسال درخواست به این *endpoint* ، پاسخ زیر باید برگردانده شود:
```json
{
"message": "ok"
}
```
### تغییر موجودی یک کاربر
این *endpoint* باید تنها برای کاربرانی قابل دسترس باشد که نقششان `ADMIN` است. با ارسال درخواست به این *endpoint* بههمراه پارامتر `balance` در بدنهی درخواست، مقدار موجودی کاربر ورودی باید بهروز شود.
### دریافت اطلاعات استادیومها
با ارسال درخواست به این *endpoint* ، اطلاعات همهی استادیومها در قالب یک آرایه باید برگردانده شوند.
### ایجاد استادیوم جدید
این *endpoint* باید تنها برای کاربرانی قابل دسترس باشد که نقششان `ADMIN` است. یک استادیوم با اطلاعات اولیهی دادهشده ایجاد میشود و مشخصات آن برگردانده میشود. مقادیر `name` و `capacity` در بدنهی درخواست ارسال میشوند. در صورتی که مقدار `balance` واردشده منفی باشد، کد پاسخ باید `400` باشد و بدنهی پاسخ باید بهصورت زیر باشد:
```json
{
"message": "Error: invalid balance"
}
```
در صورتی که کاربری با شناسهی واردشده موجود نباشد، کد پاسخ باید `404` باشد و بدنهی پاسخ باید بهصورت زیر باشد:
```json
{
"message": "Error: user not found"
}
```
### دریافت اطلاعات یک استادیوم
با ارسال درخواست به این *endpoint* ، اطلاعات استادیومی که شناسهی آن وارد شده است باید برگردانده شود. در صورتی که استادیومی با شناسهی واردشده وجود نداشته باشد، کد پاسخ باید `404` باشد و بدنهی پاسخ باید بهصورت زیر باشد:
```json
{
"message": "Error: stadium not found"
}
```
### حذف یک استادیوم
این *endpoint* باید تنها برای کاربرانی قابل دسترس باشد که نقششان `ADMIN` است. با ارسال درخواست به این *endpoint* ، استادیومی که شناسهی آن وارد شده است باید حذف شود و کد پاسخ باید `204` باشد. در صورتی که استادیومی با شناسهی واردشده وجود نداشته باشد، کد پاسخ باید `404` باشد و بدنهی پاسخ باید بهصورت زیر باشد:
```json
{
"message": "Error: stadium not found"
}
```
### دریافت اطلاعات تیمها
با ارسال درخواست به این *endpoint* ، اطلاعات همهی تیمها در قالب یک آرایه باید برگردانده شوند.
### ایجاد تیم جدید
این *endpoint* باید تنها برای کاربرانی قابل دسترس باشد که نقششان `ADMIN` است. با ارسال درخواست به این *endpoint* ، یک تیم با اطلاعات اولیهی دادهشده ایجاد میشود و مشخصات آن برگردانده میشود. مقدار `name` در بدنهی درخواست ارسال میشوند. در صورتی که تیمی با نام واردشده از قبل وجود داشته باشد، کد پاسخ باید `400` باشد.
### دریافت اطلاعات یک تیم
با ارسال درخواست به این *endpoint* ، اطلاعات تیمی که شناسهی آن وارد شده است باید برگردانده شود. در صورتی که تیمی با شناسهی واردشده وجود نداشته باشد، کد پاسخ باید `404` باشد و بدنهی پاسخ باید بهصورت زیر باشد:
```json
{
"message": "Error: team not found"
}
```
### حذف یک تیم
این *endpoint* باید تنها برای کاربرانی قابل دسترس باشد که نقششان `ADMIN` است. با ارسال درخواست به این *endpoint* ، تیمی که شناسهی آن وارد شده است باید حذف شود و کد پاسخ باید `204` باشد. در صورتی که تیمی با شناسهی واردشده وجود نداشته باشد، کد پاسخ باید `404` باشد و بدنهی پاسخ باید بهصورت زیر باشد:
```json
{
"message": "Error: team not found"
}
```
### دریافت اطلاعات مسابقات
با ارسال درخواست به این *endpoint* ، اطلاعات همهی مسابقات در قالب یک آرایه باید برگردانده شوند.
### ایجاد مسابقهی جدید
این *endpoint* باید تنها برای کاربرانی قابل دسترس باشد که نقششان `ADMIN` است. یک مسابقه با اطلاعات اولیهی دادهشده ایجاد میشود و مشخصات آن برگردانده میشود. مقادیر زیر در بدنهی درخواست ارسال میشوند:
+ شناسهی تیم میزبان (`home_id`)
+ شناسهی تیم میهمان (`away_id`)
+ شناسهی استادیوم (`stadium_id`)
+ تاریخ برگزاری مسابقه (`date`) با فرمت `yyyy-MM-dd`
اگر از تاریخ مسابقه گذشته باشد، کد پاسخ باید `400` باشد و بدنهی پاسخ باید بهصورت زیر باشد:
```json
{
"message": "Error: the given date has been passed"
}
```
در صورتی که شناسهی تیم میزبان معتبر نباشد، کد پاسخ باید `400` باشد و بدنهی پاسخ باید بهصورت زیر باشد:
```json
{
"message": "Error: invalid home team id"
}
```
در صورتی که شناسهی تیم میهمان معتبر نباشد، کد پاسخ باید `400` باشد و بدنهی پاسخ باید بهصورت زیر باشد:
```json
{
"message": "Error: invalid away team id"
}
```
در صورتی که شناسهی استادیوم معتبر نباشد، کد پاسخ باید `400` باشد و بدنهی پاسخ باید بهصورت زیر باشد:
```json
{
"message": "Error: invalid stadium id"
}
```
اگر استادیوم در تاریخ ذکرشده رزرو باشد (مسابقهی دیگری در آن روز در استادیوم وجود داشته باشد)، کد پاسخ باید `400` باشد و بدنهی پاسخ باید بهصورت زیر باشد:
```json
{
"message": "Error: stadium is full in the given date"
}
```
### دریافت اطلاعات یک مسابقه
با ارسال درخواست به این *endpoint* ، اطلاعات مسابقهای که شناسهی آن وارد شده است باید برگردانده شود. در صورتی که مسابقهای با شناسهی واردشده وجود داشته باشد، کد پاسخ باید `404` باشد و بدنهی پاسخ باید بهصورت زیر باشد:
```json
{
"message": "Error: match not found"
}
```
### حذف یک مسابقه
این *endpoint* باید تنها برای کاربرانی قابل دسترس باشد که نقششان `ADMIN` است. با ارسال درخواست به این *endpoint* ، مسابقهای که شناسهی آن وارد شده است باید حذف شود و کد پاسخ باید `204` باشد. در صورتی که مسابقهای با شناسهی واردشده وجود نداشته باشد، کد پاسخ باید `404` باشد و بدنهی پاسخ باید بهصورت زیر باشد:
```json
{
"message": "Error: match not found"
}
```
### دریافت اطلاعات مجموعه جایگاهها
با ارسال درخواست به این *endpoint* ، اطلاعات همهی مجموعه جایگاهها در قالب یک آرایه باید برگردانده شوند.
### ایجاد مجموعه جایگاه جدید
این *endpoint* باید تنها برای کاربرانی قابل دسترس باشد که نقششان `ADMIN` است. یک مجموعه جایگاه با اطلاعات اولیهی دادهشده ایجاد میشود و مشخصات آن برگردانده میشود. مقادیر زیر در بدنهی درخواست ارسال میشوند:
+ عدد شروع صندلیهای مجموعه جایگاه (`min_number`)
+ عدد پایان صندلیهای مجموعه جایگاه (`max_number`)
+ شناسهی مسابقه (`match_id`)
+ قیمت صندلیهای موجود در مجموعه جایگاه (`price`)
در صورتی که مسابقهای با شناسهی واردشده موجود نباشد، کد پاسخ باید `400` باشد و بدنهی پاسخ باید بهصورت زیر باشد:
```json
{
"message": "Error: invalid match id"
}
```
در صورتی که مقدار `min_number` کوچکتر از ۱ باشد، کد پاسخ باید `400` باشد و بدنهی پاسخ باید بهصورت زیر باشد:
```json
{
"message": "Error: invalid min number"
}
```
در صورتی که مقدار `max_number` کوچکتر از `min_number` باشد یا بزرگتر از ظرفیت استادیوم باشد، کد پاسخ باید `400` باشد و بدنهی پاسخ باید بهصورت زیر باشد:
```json
{
"message": "Error: invalid max number"
}
```
در صورتی که مقدار `price` منفی باشد، کد پاسخ باید `400` باشد و بدنهی پاسخ باید بهصورت زیر باشد:
```json
{
"message": "Error: invalid price"
}
```
اگر مجموعه جایگاهی برای بازی موردنظر وجود داشته باشد که شماره صندلی مشترکی با مجموعه جایگاه فعلی داشته باشد، کد پاسخ باید `400` باشد و بدنهی پاسخ باید بهصورت زیر باشد:
```json
{
"message": "Error: overlapping seat class exists"
}
```
### دریافت اطلاعات یک مجموعه جایگاه
با ارسال درخواست به این *endpoint* ، اطلاعات مجموعه جایگاهی که شناسهی آن وارد شده است باید برگردانده شود. در صورتی که مجموعه جایگاهی با شناسهی واردشده وجود نداشته باشد، کد پاسخ باید `404` باشد.
### حذف یک مجموعه جایگاه
این *endpoint* باید تنها برای کاربرانی قابل دسترس باشد که نقششان `ADMIN` است. با ارسال درخواست به این *endpoint* ، مجموعه جایگاهی که شناسهی آن وارد شده است باید حذف شود و کد پاسخ باید `204` باشد. در صورتی که مجموعه جایگاهی با شناسهی واردشده وجود نداشته باشد، کد پاسخ باید `404` باشد.
### دریافت لیست بلیتهای کاربر فعلی
با ارسال درخواست به این *endpoint* ، لیست بلیتهای کاربر واردشدهی فعلی باید در قالب یک آرایه برگردانده شود.
### خرید بلیت برای یک صندلی
با ارسال درخواست به این *endpoint* ، عملیات خرید بلیت یک صندلی برای کاربر فعلی باید انجام شود. مقادیر `match_id` و `seat_number` در بدنهی درخواست موجود خواهند بود.
در صورتی که مسابقهای با شناسهی واردشده موجود نباشد، کد پاسخ باید `400` باشد و بدنهی پاسخ باید بهصورت زیر باشد:
```json
{
"message": "Error: invalid match id"
}
```
در صورتی که از تاریخ مسابقه گذشته باشد، کد پاسخ باید `400` باشد و بدنهی پاسخ باید بهصورت زیر باشد:
```json
{
"message": "Error: the match has been finished"
}
```
در صورتی که مقدار `seat_number` کوچکتر از ۱ باشد یا بزرگتر از ظرفیت استادیوم بازی باشد، کد پاسخ باید `400` باشد و بدنهی پاسخ باید بهصورت زیر باشد:
```json
{
"message": "Error: invalid seat number"
}
```
در صورتی که مجموعه جایگاهی برای شماره صندلی موردنظر تعریف نشده باشد، کد پاسخ باید `400` باشد و بدنهی پاسخ باید بهصورت زیر باشد:
```json
{
"message": "Error: the seat is not available"
}
```
در صورتی که کاربر فعلی، صندلی فعلی را از قبل خریده باشد، کد پاسخ باید `400` باشد و بدنهی پاسخ باید بهصورت زیر باشد:
```json
{
"message": "Error: you have already reserved this seat"
}
```
در صورتی که کاربر دیگری صندلی فعلی را از قبل خریده باشد، کد پاسخ باید `400` باشد و بدنهی پاسخ باید بهصورت زیر باشد:
```json
{
"message": "Error: the seat is reserved by another user"
}
```
در صورتی که میزان موجودی کاربر کمتر از قیمت صندلی باشد، کد پاسخ باید `400` باشد و بدنهی پاسخ باید بهصورت زیر باشد:
```json
{
"message": "Error: not enough balance"
}
```
# نکات
+ در *endpoint* هایی که نیازمند دسترسی کاربر هستند، در صورت عدم وجود دسترسی، کد پاسخ `403` باید برگردانده شود. در صورتی که هیچ کاربری وارد برنامه نشده باشد، کد پاسخ `401` باید برگردانده شود.
+ فیلدهایی که در پاسخها باید برگردند، باید مطابق با تعریف مدلها باشند.
# آنچه باید آپلود کنید
پس از پیادهسازی موارد خواستهشده، پوشهی `src` پروژه را زیپ کرده و ارسال کنید. توجه داشته باشید که فقط تغییرات اعمالشده در پوشهی `src/main/java/org/quera/ticket` در نظر گرفته میشوند.