پیش‌بینی


سلیب و افض به یک مشکل مشترک رسیدند. آن‌ها تصمیم گرفتند تا از شرّ سرچ هرساله خود راحت شوند. هر دوی آن‌ها همیشه فراموش می‌کردند که جام جهانی بعدی در چه سالی برگزار می‌شود و همواره یکی از دو عبارت زیر را سرچ می‌کردند:‌

جام جهانی بعدی کی است

و یا

when is the next world cup

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

جزئیات پروژه🔗

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

ساختار فایل‌های پروژه به‌صورت زیر است:

WorldCup
├── Predictor.java
└── test
    └── PredictorSampleTest.java
Plain text

شما باید تابع predict موجود در فایل Predictor.java را مطابق با خواست مسئله پیاده‌سازی کنید. امضای تابع مورد نظر به شکل زیر است:

extensionFromNamePredictor.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
    }
}
Java

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

مثال🔗

extensionFromNameTerminal
System.out.println(predict(2021)); // 2022
System.out.println(predict(2022)); // 2022
System.out.println(predict(2023)); // 2026
Java

نکات🔗

  • توجه داشته باشید که جام جهانی تنها در سال‌هایی برگزار می‌شود که باقی مانده عدد سال بر عدد ۴ برابر با عدد ۲ باشد.
  • مقدار خواسته شده مسئله را برگردانید و آن را پرینت نکنید.
  • در این مسئله تنها مجاز به استفاده از کتاب‌خانه‌های استاندارد جاوا هستید.

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

پس از پیاده‌سازی موارد خواسته‌شده، فایل Predictor.java را آپلود کنید.

کلاس‌ساز 🎼


امیرحسین که فردی است جوان و جویای نام‌! به‌دنبال پیاده‌سازی سیستمی است که دنیا را تکان دهد. او فکری در سر دارد که احساس می‌کند اولین قدم از رسیدن به یک سیستم هوشمند قوی است.

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

جزئیات پروژه🔗

پروژه‌ی اولیه را از این لینک دانلود کنید. ساختار فایل‌های پروژه اولیه به‌صورت زیر است:

.
├── ClassDetail
├── ClassTypes
├── ClassUtil
├── Method
└── OopType
Plain text

وظیفه اصلی شما در این سوال، تکمیل کلاس 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 دارد. برای این کار کد زیر را می‌نویسیم و از متد کلاسی که تکمیل کردید استفاده می‌کنیم:

extensionFromNameMain.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

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

extensionFromNameMonth.java
public enum Month {
 NAME;
}
Java

در مثالی دیگر فرض کنید قصد داریم تا کلاسی بسازیم که دارای مقادیری به‌صورت زیر باشد:

extensionFromNameMain.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));
Java

که در این حالت متغیر code باید به‌صورت زیر باشد:

extensionFromNameMonth.java
import java.lang.Object;
import java.lang.String;
public class Month extends Object {
String name;
}
Java

نکات🔗

  • کلاس شما حتما باید بدون مشکل کامپایل شود.
  • تضمین می‌شود نام کلاس‌هایی که در پراپرتی oop قرار داده می‌شود، حتما وجود دارند و از پکیج‌های استاندارد جاوا هستند.
  • کلاسی که می‌سازید نباید هیچ کلاس اضافی را import کرده باشد.
  • رعایت تمام موارد شی‌گرایی، به‌عنوان مثال هر کلاس فقط می‌تواند یک کلاس را extends و ... ، باید در کلاس شما رعایت شده باشد.
  • در صورت وجود مشکل در قسمت extends یا implements ، کلاس شما باید کامل ساخته شود و فقط extends یا implements را نادیده بگیرد.
  • اگر کلاسی متد داشت، بدنه متد‌ها باید خالی باشد و تضمین می‌شود نوع خروجی متد‌ها void باشد.

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

پس از پیاده‌سازی موارد خواسته‌شده، کلاس ClassUtil را زیپ کرده و ارسال کنید.

تزریق خودکار


تزریق خودکار

ابوالفضل مدت زیادی است که با فریمورک Spring Boot کار می‌کند. اخیراً او به این فکر فرو رفته که قابلیت‌های مختلف این فریمورک چگونه کار می‌کنند. برای درک عمیق‌تر این موضوع، او می‌خواهد بداند قابلیت autowiring که تزریق وابستگی (dependency injection) خودکار با استفاده از آن انجام می‌شود چگونه کار می‌کند. از شما می‌خواهیم نسخه‌ی ساده‌ای از این بخش فریمورک Spring Boot را برای او بنویسید.

جزئیات پروژه🔗

پروژه‌ی اولیه را از این لینک دانلود کنید. ساختار فایل‌های پروژه به‌صورت زیر است:

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
Plain text

انوتیشن @Component🔗

از این انوتیشن در کلاس‌هایی استفاده می‌شود که بخواهیم امکان استفاده از آن‌ها در تزریق وابستگی خودکار فراهم باشد. این انوتیشن شامل پارامتر value از نوع String است.

انوتیشن @Autowired🔗

از این انوتیشن زمانی استفاده می‌شود که بخواهیم کانستراکتور موردنظر را جهت فراخوانی هنگام تزریق وابستگی خودکار مشخص کنیم. اگر کلاس موردنظر تنها شامل یک کانستراکتور باشد، نیازی به استفاده از این انوتیشن نیست. در غیر این‌صورت، فقط یکی از کانستراکتورهای کلاس باید دارای این انوتیشن باشد.

انوتیشن @Qualifier🔗

از این انوتیشن زمانی استفاده می‌شود که بخواهیم از بین چند پیاده‌سازی برای یک اینترفیس یا کلاس، یکی را برای autowiring انتخاب کنیم. این انوتیشن شامل پارامتر value از نوع String است.

کلاس Injector🔗

این کلاس، وظیفه‌ی اصلی قابلیت autowiring را برعهده دارد. این کلاس شامل متدی با نام get و با امضای زیر است:

public static <T> T get(Class<T> typeClass)
Java

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

نکات زیر هنگام پیاده‌سازی متد 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}

جزئیات پروژه🔗

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

تعریف شرکت بیمه🔗

در برنامه شما باید بتوان شرکت جدیدی ثبت کرد. شرکت‌ها باید در جدولی به نام companies ذخیره شوند و اطلاعات این جدول به‌صورت زیر است:

نام ستون نوع
name String

هم‌چنین این شرکت می‌تواند چندین بیمه (insurances) ایجاد کند.

برای ایجاد شرکت بیمه شما باید اندپوینتی با اطلاعات زیر ایجاد کنید:

URL:
"POST /companies/save"

Request: 
content-type: "application/json"
{
  "name": "shahram"
}
JSON

اگر شرکت ذخیره شد باید عبارت 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

برای ایجاد بیمه‌ها شما باید اندپوینتی با اطلاعات زیر ایجاد کنید:

URL:
"POST /insurances/save"

Request:
content-type: "application/json"
{
  "type": "PERSON",
  "name": "shakhs",
  "price": 300000,
  "company_id": 1,
  "minAge": 20
}
JSON

اگر بیمه ذخیره شد باید عبارت Insurance saved. و اگر هر خطایی رخ داد، عبارت Insurance saving problem! را با وضعیت BAD_REQUEST برگردانید.

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

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

نکات🔗

  • برای این پروژه از دیتابیس h2 استفاده شده است.
  • شما مجاز به ایجاد هر کلاسی در مسیر org/quera/bime هستید، فقط باید پروژه شما خواسته‌های مسئله را به‌خوبی پیاده‌سازی کرده باشد.

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

پس از پیاده‌سازی موارد خواسته‌شده، این پروژه را زیپ کرده و ارسال کنید.

استادیوم


در این سؤال، باید سامانه‌ی فروش بلیت مسابقات فوتبال در استادیوم‌های مختلف را پیاده‌سازی کنید!

جزئیات پروژه🔗

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

  • این پروژه از Maven استفاده می‌کند و وابستگی‌ها در POM تعریف شده‌اند. امکان تغییر این وابستگی‌ها وجود ندارد.
  • برای اجرای تست‌ها، از دیتابیس H2 استفاده می‌شود.
  • در این پروژه، وابستگی Project Lombok تعریف شده و قابل استفاده است.
  • بسته‌ی 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 ، پاسخ زیر باید برگردانده شود:

{
    "message": "ok"
}
JSON

تغییر موجودی یک کاربر🔗

این endpoint باید تنها برای کاربرانی قابل دسترس باشد که نقش‌شان ADMIN است. با ارسال درخواست به این endpoint به‌همراه پارامتر balance در بدنه‌ی درخواست، مقدار موجودی کاربر ورودی باید به‌روز شود.

دریافت اطلاعات استادیوم‌ها🔗

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

ایجاد استادیوم جدید🔗

این endpoint باید تنها برای کاربرانی قابل دسترس باشد که نقش‌شان ADMIN است. یک استادیوم با اطلاعات اولیه‌ی داده‌شده ایجاد می‌شود و مشخصات آن برگردانده می‌شود. مقادیر name و capacity در بدنه‌ی درخواست ارسال می‌شوند. در صورتی که مقدار balance واردشده منفی باشد، کد پاسخ باید 400 باشد و بدنه‌ی پاسخ باید به‌صورت زیر باشد:

{
    "message": "Error: invalid balance"
}
JSON

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

{
    "message": "Error: user not found"
}
JSON

دریافت اطلاعات یک استادیوم🔗

با ارسال درخواست به این endpoint ، اطلاعات استادیومی که شناسه‌ی آن وارد شده است باید برگردانده شود. در صورتی که استادیومی با شناسه‌ی واردشده وجود نداشته باشد، کد پاسخ باید 404 باشد و بدنه‌ی پاسخ باید به‌صورت زیر باشد:

{
    "message": "Error: stadium not found"
}
JSON

حذف یک استادیوم🔗

این endpoint باید تنها برای کاربرانی قابل دسترس باشد که نقش‌شان ADMIN است. با ارسال درخواست به این endpoint ، استادیومی که شناسه‌ی آن وارد شده است باید حذف شود و کد پاسخ باید 204 باشد. در صورتی که استادیومی با شناسه‌ی واردشده وجود نداشته باشد، کد پاسخ باید 404 باشد و بدنه‌ی پاسخ باید به‌صورت زیر باشد:

{
    "message": "Error: stadium not found"
}
JSON

دریافت اطلاعات تیم‌ها🔗

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

ایجاد تیم جدید🔗

این endpoint باید تنها برای کاربرانی قابل دسترس باشد که نقش‌شان ADMIN است. با ارسال درخواست به این endpoint ، یک تیم با اطلاعات اولیه‌ی داده‌شده ایجاد می‌شود و مشخصات آن برگردانده می‌شود. مقدار name در بدنه‌ی درخواست ارسال می‌شوند. در صورتی که تیمی با نام واردشده از قبل وجود داشته باشد، کد پاسخ باید 400 باشد.

دریافت اطلاعات یک تیم🔗

با ارسال درخواست به این endpoint ، اطلاعات تیمی که شناسه‌ی آن وارد شده است باید برگردانده شود. در صورتی که تیمی با شناسه‌ی واردشده وجود نداشته باشد، کد پاسخ باید 404 باشد و بدنه‌ی پاسخ باید به‌صورت زیر باشد:

{
    "message": "Error: team not found"
}
JSON

حذف یک تیم🔗

این endpoint باید تنها برای کاربرانی قابل دسترس باشد که نقش‌شان ADMIN است. با ارسال درخواست به این endpoint ، تیمی که شناسه‌ی آن وارد شده است باید حذف شود و کد پاسخ باید 204 باشد. در صورتی که تیمی با شناسه‌ی واردشده وجود نداشته باشد، کد پاسخ باید 404 باشد و بدنه‌ی پاسخ باید به‌صورت زیر باشد:

{
    "message": "Error: team not found"
}
JSON

دریافت اطلاعات مسابقات🔗

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

ایجاد مسابقه‌ی جدید🔗

این endpoint باید تنها برای کاربرانی قابل دسترس باشد که نقش‌شان ADMIN است. یک مسابقه با اطلاعات اولیه‌ی داده‌شده ایجاد می‌شود و مشخصات آن برگردانده می‌شود. مقادیر زیر در بدنه‌ی درخواست ارسال می‌شوند:

  • شناسه‌ی تیم میزبان (home_id)
  • شناسه‌ی تیم میهمان (away_id)
  • شناسه‌ی استادیوم (stadium_id)
  • تاریخ برگزاری مسابقه (date) با فرمت yyyy-MM-dd

اگر از تاریخ مسابقه گذشته باشد، کد پاسخ باید 400 باشد و بدنه‌ی پاسخ باید به‌صورت زیر باشد:

{
    "message": "Error: the given date has been passed"
}
JSON

در صورتی که شناسه‌ی تیم میزبان معتبر نباشد، کد پاسخ باید 400 باشد و بدنه‌ی پاسخ باید به‌صورت زیر باشد:

{
    "message": "Error: invalid home team id"
}
JSON

در صورتی که شناسه‌ی تیم میهمان معتبر نباشد، کد پاسخ باید 400 باشد و بدنه‌ی پاسخ باید به‌صورت زیر باشد:

{
    "message": "Error: invalid away team id"
}
JSON

در صورتی که شناسه‌ی استادیوم معتبر نباشد، کد پاسخ باید 400 باشد و بدنه‌ی پاسخ باید به‌صورت زیر باشد:

{
    "message": "Error: invalid stadium id"
}
JSON

اگر استادیوم در تاریخ ذکرشده رزرو باشد (مسابقه‌ی دیگری در آن روز در استادیوم وجود داشته باشد)، کد پاسخ باید 400 باشد و بدنه‌ی پاسخ باید به‌صورت زیر باشد:

{
    "message": "Error: stadium is full in the given date"
}
JSON

دریافت اطلاعات یک مسابقه🔗

با ارسال درخواست به این endpoint ، اطلاعات مسابقه‌ای که شناسه‌ی آن وارد شده است باید برگردانده شود. در صورتی که مسابقه‌ای با شناسه‌ی واردشده وجود داشته باشد، کد پاسخ باید 404 باشد و بدنه‌ی پاسخ باید به‌صورت زیر باشد:

{
    "message": "Error: match not found"
}
JSON

حذف یک مسابقه🔗

این endpoint باید تنها برای کاربرانی قابل دسترس باشد که نقش‌شان ADMIN است. با ارسال درخواست به این endpoint ، مسابقه‌ای که شناسه‌ی آن وارد شده است باید حذف شود و کد پاسخ باید 204 باشد. در صورتی که مسابقه‌ای با شناسه‌ی واردشده وجود نداشته باشد، کد پاسخ باید 404 باشد و بدنه‌ی پاسخ باید به‌صورت زیر باشد:

{
    "message": "Error: match not found"
}
JSON

دریافت اطلاعات مجموعه جایگاه‌ها🔗

با ارسال درخواست به این endpoint ، اطلاعات همه‌ی مجموعه جایگاه‌ها در قالب یک آرایه باید برگردانده شوند.

ایجاد مجموعه جایگاه جدید🔗

این endpoint باید تنها برای کاربرانی قابل دسترس باشد که نقش‌شان ADMIN است. یک مجموعه جایگاه با اطلاعات اولیه‌ی داده‌شده ایجاد می‌شود و مشخصات آن برگردانده می‌شود. مقادیر زیر در بدنه‌ی درخواست ارسال می‌شوند:

  • عدد شروع صندلی‌های مجموعه جایگاه (min_number)
  • عدد پایان صندلی‌های مجموعه جایگاه (max_number)
  • شناسه‌ی مسابقه (match_id)
  • قیمت صندلی‌های موجود در مجموعه جایگاه (price)

در صورتی که مسابقه‌ای با شناسه‌ی واردشده موجود نباشد، کد پاسخ باید 400 باشد و بدنه‌ی پاسخ باید به‌صورت زیر باشد:

{
    "message": "Error: invalid match id"
}
JSON

در صورتی که مقدار min_number کوچک‌تر از ۱ باشد، کد پاسخ باید 400 باشد و بدنه‌ی پاسخ باید به‌صورت زیر باشد:

{
    "message": "Error: invalid min number"
}
JSON

در صورتی که مقدار max_number کوچک‌تر از min_number باشد یا بزرگ‌تر از ظرفیت استادیوم باشد، کد پاسخ باید 400 باشد و بدنه‌ی پاسخ باید به‌صورت زیر باشد:

{
    "message": "Error: invalid max number"
}
JSON

در صورتی که مقدار price منفی باشد، کد پاسخ باید 400 باشد و بدنه‌ی پاسخ باید به‌صورت زیر باشد:

{
    "message": "Error: invalid price"
}
JSON

اگر مجموعه جایگاهی برای بازی موردنظر وجود داشته باشد که شماره صندلی مشترکی با مجموعه جایگاه فعلی داشته باشد، کد پاسخ باید 400 باشد و بدنه‌ی پاسخ باید به‌صورت زیر باشد:

{
    "message": "Error: overlapping seat class exists"
}
JSON

دریافت اطلاعات یک مجموعه جایگاه🔗

با ارسال درخواست به این endpoint ، اطلاعات مجموعه جایگاهی که شناسه‌ی آن وارد شده است باید برگردانده شود. در صورتی که مجموعه جایگاهی با شناسه‌ی واردشده وجود نداشته باشد، کد پاسخ باید 404 باشد.

حذف یک مجموعه جایگاه🔗

این endpoint باید تنها برای کاربرانی قابل دسترس باشد که نقش‌شان ADMIN است. با ارسال درخواست به این endpoint ، مجموعه جایگاهی که شناسه‌ی آن وارد شده است باید حذف شود و کد پاسخ باید 204 باشد. در صورتی که مجموعه جایگاهی با شناسه‌ی واردشده وجود نداشته باشد، کد پاسخ باید 404 باشد.

دریافت لیست بلیت‌های کاربر فعلی🔗

با ارسال درخواست به این endpoint ، لیست بلیت‌های کاربر واردشده‌ی فعلی باید در قالب یک آرایه برگردانده شود.

خرید بلیت برای یک صندلی🔗

با ارسال درخواست به این endpoint ، عملیات خرید بلیت یک صندلی برای کاربر فعلی باید انجام شود. مقادیر match_id و seat_number در بدنه‌ی درخواست موجود خواهند بود.

در صورتی که مسابقه‌ای با شناسه‌ی واردشده موجود نباشد، کد پاسخ باید 400 باشد و بدنه‌ی پاسخ باید به‌صورت زیر باشد:

{
    "message": "Error: invalid match id"
}
JSON

در صورتی که از تاریخ مسابقه گذشته باشد، کد پاسخ باید 400 باشد و بدنه‌ی پاسخ باید به‌صورت زیر باشد:

{
    "message": "Error: the match has been finished"
}
JSON

در صورتی که مقدار seat_number کوچک‌تر از ۱ باشد یا بزرگ‌تر از ظرفیت استادیوم بازی باشد، کد پاسخ باید 400 باشد و بدنه‌ی پاسخ باید به‌صورت زیر باشد:

{
    "message": "Error: invalid seat number"
}
JSON

در صورتی که مجموعه جایگاهی برای شماره صندلی موردنظر تعریف نشده باشد، کد پاسخ باید 400 باشد و بدنه‌ی پاسخ باید به‌صورت زیر باشد:

{
    "message": "Error: the seat is not available"
}
JSON

در صورتی که کاربر فعلی، صندلی فعلی را از قبل خریده باشد، کد پاسخ باید 400 باشد و بدنه‌ی پاسخ باید به‌صورت زیر باشد:

{
    "message": "Error: you have already reserved this seat"
}
JSON

در صورتی که کاربر دیگری صندلی فعلی را از قبل خریده باشد، کد پاسخ باید 400 باشد و بدنه‌ی پاسخ باید به‌صورت زیر باشد:

{
    "message": "Error: the seat is reserved by another user"
}
JSON

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

{
    "message": "Error: not enough balance"
}
JSON

نکات🔗

  • در endpoint هایی که نیازمند دسترسی کاربر هستند، در صورت عدم وجود دسترسی، کد پاسخ 403 باید برگردانده شود. در صورتی که هیچ کاربری وارد برنامه نشده باشد، کد پاسخ 401 باید برگردانده شود.
  • فیلدهایی که در پاسخ‌ها باید برگردند، باید مطابق با تعریف مدل‌ها باشند.

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

پس از پیاده‌سازی موارد خواسته‌شده، پوشه‌ی src پروژه را زیپ کرده و ارسال کنید. توجه داشته باشید که فقط تغییرات اعمال‌شده در پوشه‌ی src/main/java/org/quera/ticket در نظر گرفته می‌شوند.