گل یا پوچ ساده


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

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

بازیکن‌ها را با اعداد ۱ تا ۳ شماره‌گذاری می‌کنیم. در ابتدا گل در دست xx بازیکن شماره‌ی ss است که مقدار xx برابر LL یا RR است. بازی شروع می‌شود و در حین بازی، بازیکنان nn حرکت انجام می‌دهند. حرکت‌ها یکی از حالت‌های زیر را دارد:

خالی بازی kk🔗

در این حرکت بازیکن شمار‌ه‌ی kk محتوای دو دستش را جابه‌جا می‌کند. (k=1,2,3k = 1, 2, 3)

جابه‌جایی kk و k+1k+1🔗

در این حرکت بازیکن شماره‌ی kk محتوای دست xx خودش را با محتوای دست yy بازیکن k+1k+1 جابه‌جا می‌کند. (k=1,2k = 1, 2 و x,y{L,R}x, y \in \{L, R\})

مشتی‌ علی گزارش این nn حرکت را به ترتیب به شما می‌دهد. شما باید شماره‌ی بازیکنی که گل در دست آن است و اسم دست آن بازیکن را نشان می‌دهد.

ورودی🔗

در سطر اول ورودی،‌ عدد صحیح و مثبت nn داده می‌شود. 1n1001 \leq n \leq 100

در سطر دوم ورودی، عدد ss و کاراکتر xx داده می‌شود. s{1,2,3},x{L,R}s \in \{1, 2, 3\}, \quad x \in \{L, R\}

در nn سطر بعدی در هر سطر یکی از حرکت‌ها داده می‌شود.

حرکت نوع اول به صورت 1 k1\ k است. که یعنی بازیکن kkام محتوای دو دستش را عوض می‌کند.

k{1,2,3}k \in \{1, 2, 3\}

حرکت نوع دوم به صورت 2 k x y2\ k\ x\ y که یعنی بازیکن kkام محتوای دست xx را به دست yy بازیکن k+1k+1ام می‌دهد.

k{1,2},x,y{L,R}k \in \{1, 2\}, \quad x, y \in \{L, R\}

خروجی🔗

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

مثال‌ها🔗

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

5
2 L
2 2 R L
2 1 L L
1 1
1 2
1 3
Plain text

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

1 R
Plain text

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

2
3 R
1 1
2 1 R R
Plain text

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

3 R
Plain text

دارت بازی


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

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

توضیح تصویر

در بازی دارت، قوانین امتیازدهی به این صورت است:

تخته دارت به ۲۰ بخش مساوی تقسیم شده که هر بخش عددی بین ۱ تا ۲۰ را نشان می‌دهد.

در مرکز تخته دارت یک بخش کوچک به نام «بولس‌آی» (Bullseye) وجود دارد که از دو بخش تشکیل شده است. حلقه‌ی مرکزی کوچک‌تر، دایره‌ای با شعاع ۱ سانتی‌متر با ۵۰ امتیاز و حلقه‌ی مرکزی بزرگ‌تر، دایره‌ای با شعاع ۲ سانتی‌متر و ۲۵ امتیاز دارد.

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

حلقه داخلی (حلقه دو‌برابر): اگر دارت به این حلقه برخورد کند، امتیاز آن بخش دو برابر می‌شود. اندازه‌ی این بخش ۱ سانتی‌متر است.

تخته بیرونی (خارج از بخش‌های امتیازی): دارت به تخته نخورده و امتیازی ندارد.

اندازه‌ی شعاع دایره‌ی خارجی (با حلقه سه‌برابر) ۱۰ سانتی‌متر و اندازه‌ی شعاع دایره‌ی داخلی (با حلقه دوبرابر) ۶ سانتی‌متر است.

آن‌ها دچار خطای ارزیابی هستند و اکنون پرتاب‌های خودشان را روی صفحه انجام داده‌اند و سپس می‌خواهند ترتیب اعداد ۱ تا ۲۰ را طوری تغییر دهند که امتیاز باقر خیلی بیشتر از امتیاز علی شود. آن‌ها نمی‌توانند امتیاز بولس‌آی را تغییر دهند.

حال می‌دانیم باقر nn پرتاب کرده و علی mm پرتاب می‌خواهیم بدانیم در بین تمام عددگذاری‌های مختلف در کدام حالت اختلاف امتیاز باقر از علی بیشتر است.

پرتاب‌های باقر و علی را به صورت rr و θ\theta می‌دهیم یعنی در چه شعاع و زاویه‌ای دارت پرتاب شده است. مقدار rr برحسب سانتی‌متر و نشان دهنده‌ی فاصله از مرکز دارت است. همچنین θ\theta زاویه‌ی نقطه‌ی پرتاب شده از محور xxها را نشان می‌دهد. برای مثال ناحیه‌ی شماره‌ی ۱۳ در شکل، زاویه‌ی ۹ تا ۲۷ درجه است.

تضمین می‌شود هیچ‌وقت پرتابی به ناحیه‌ی مرزی نمی‌خورد.

ورودی🔗

در سطر اول ورودی، دو عدد صحیح و مثبت nn و mm داده می‌شود.

1n,m1001 \leq n, m \leq 100

در n+mn+m سطر بعدی در هر سطر دو عدد rr و θ\theta داده می‌شود که nn پرتاب اول برای باقر و mm تای بعدی برای علی است.

تضمین می‌شود هیچ‌وقت پرتابی به ناحیه‌ی مرزی نمی‌خورد.

خروجی🔗

یک عدد صحیح برابر بیشترین اختلاف امتیازی که می‌تواند باقر از علی پیدا کند.

مثال‌ها🔗

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

3 1
5.285 61.600
1.697 76.563
1.820 226.466
0.820 324.470
Plain text

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

40
Plain text

در این حالت، باقر ۳ دارت و علی ۱ دارت پرتاب کرده‌اند. باقر پرتاب دوم و سومش به بولس‌آی ۲۵ امتیازی و پرتاب علی به بولس‌آی ۵۰ امتیازی برخورد کرده است. پرتاب اول باقر در حلقه‌ی داخلی (دو برابر) خورده است. بنابراین اگر امتیازها را طوری تغییر دهیم که ۲۰ امتیاز روی آن قطعه قرار بگیرد، اختلاف امتیاز باقر و علی بیشینه و برابر است با: 2×20+25+2550=402 \times 20 + 25 + 25 - 50 = 40

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

2 2
1.790 119.791
9.260 178.282
0.850 166.297
9.538 31.585
Plain text

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

32
Plain text

در این حالت، باقر و علی هر کدام ۲ دارت پرتاب کرده‌اند. پرتاب اول باقر به بولس‌ای ۲۵ امتیازی و پرتاب اول علی به بولس‌آی ۵۰ امتیازی برخورد کرده است. پرتاب‌های دوم باقر و علی هر دو به حلقه‌های بیرونی (سه برابر) خورده است ولی در دو ناحیه‌ی مختلف. اگر اعداد ۱ تا ۲۰ را طوری قرار دهیم که ناحیه‌ی باقر ۲۰ امتیاز و ناحیه‌ی علی ۱ امتیاز داشته باشد، اختلاف امتیاز باقر و علی بیشینه و برابر است با:

25+3×20503×1=3225 + 3 \times 20 - 50 - 3 \times 1 = 32

تیم‌های توسعه منظم


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

در یک شرکت nn برنامه‌نویس مشغول به کار هستند. هر کدام از این nn نفر در برخی از زمینه‌های Front-end، Back-end یا Product Mangement تخصص دارد.

تخصص‌های هر شخص را با یک رشته شامل حروف B، F و P به صورت مرتب‌شده الفبایی به ما داده شده است.

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

حال از شما می‌خواهیم برنامه‌ای بنویسید که این بیشترین تعداد تیم را محاسبه کند.

ورودی🔗

در سطر اول ورودی، عدد صحیح و مثبت tt آمده که تعداد تست‌ها را نشان می‌دهد.

1t100001 \leq t \leq 10 \,000

در سطر اول هر تست، عدد صحیح و مثبت nn داده می‌شود که تعداد برنامه‌نویس‌ها را نشان می‌دهد.

1n1001 \leq n \leq 100

در nn سطر بعدی در هر سطر یک رشته داده می‌شود که رشته‌ی سطر iiام تخصص برنامه‌نویس iiام را نشان می‌دهد.

خروجی🔗

در تنها سطر خروجی، یک عدد صحیح برابر بیشترین تعداد تیم کامل را چاپ کنید.

مثال‌ها🔗

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

3
5
B F P BFP BF
6
BF BP FP B BFP P
2
B BFP
Plain text

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

1
2
0
Plain text

در نمونه‌ی اول تیم‌بندی می‌تواند به صورت زیر باشد: {B,F,P}\{B, F, P\}

در نمونه‌ی دوم تیم‌بندی می‌تواند به صورت زیر باشد: {BF,BP,FP}{B,BFP,P}\{BF, BP, FP\} \quad \{B, BFP, P\}

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

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


کد شما باید روی PostgreSQL قابل اجرا باشد.


جزئیات پایگاه‌داده🔗

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

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

ایمپورت کردن داده‌های اولیه

از نصب بودن PostgreSQL روی سیستم خود اطمینان حاصل کنید.

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

۱- با استفاده CLI دستور زیر را وارد کنید تا داده‌های اولیه ایمپورت شوند:

psql -U postgres -f /path/to/initial.sql
Shell

که در این دستور مسیر فایل initial.sql را به صورت مطلق یا نسبی می‌توانید آدرس‌دهی کنید.

۲- اگر GUI را ترجیح می‌دهید، پس از نصب دیتاگریپ و اتصال به PostgreSQL با یوزر postgres، باید روی دیتاسورس و کانکشن postgres راست‌کلیک کنید و از منوی SQL Scripts، گزینه‌ی Run SQL Script را انتخاب کنید. سپس فایل initial.sql را پیدا و تایید کنید. در انتها روی Run کلیک کنید تا اسکریپت اجرا شود و داده‌ها وارد دیتابیس شوند.

توضیحات جداول دیتاست

جدول address (آدرس‌ها)🔗

این جدول اطلاعات مربوط به آدرس‌ها را ذخیره می‌کند.

نام ستون نوع داده توضیحات
id integer شناسه‌ی یکتا برای آدرس (کلید اصلی)
city varchar(100) شهر
country varchar(100) کشور
country_code varchar(100) کد کشور
zip_code integer کد پستی

جدول company (شرکت‌ها)🔗

این جدول اطلاعات مربوط به شرکت‌ها را ذخیره می‌کند.

نام ستون نوع داده توضیحات
id integer شناسه‌ی یکتا برای شرکت (کلید اصلی)
name varchar(100) نام شرکت
address_id bigint شناسه‌ی آدرس مرتبط (کلید خارجی به جدول address)

جدول product (محصولات)🔗

این جدول اطلاعات مربوط به محصولات را ذخیره می‌کند.

نام ستون نوع داده توضیحات
id integer شناسه‌ی یکتا برای محصول (کلید اصلی)
name varchar(100) نام محصول
category varchar(100) دسته‌بندی محصول
price integer قیمت محصول

جدول product_company (شرکت-محصول)🔗

این جدول یک رابطه‌ی چند به چند بین شرکت‌ها و محصولات ایجاد می‌کند.

نام ستون نوع داده توضیحات
id integer شناسه‌ی یکتا برای رابطه (کلید اصلی)
company_id bigint شناسه‌ی شرکت (کلید خارجی به جدول company)
product_id bigint شناسه‌ی محصول (کلید خارجی به جدول product)

جدول user (کاربران)🔗

این جدول اطلاعات مربوط به کاربران را ذخیره می‌کند.

نام ستون نوع داده توضیحات
id integer شناسه‌ی یکتا برای کاربر (کلید اصلی)
first_name text نام کاربر
last_name text نام خانوادگی کاربر
email text ایمیل کاربر
address_id integer شناسه‌ی آدرس مرتبط (کلید خارجی به جدول address)
company_id integer شناسه‌ی شرکت مرتبط (کلید خارجی به جدول company)
username text نام کاربری

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

مطلوبات🔗

کوئری‌هایی بنویسید که خروجی‌های مطلوب زیر را به‌دست آورد (توجه کنید که هر کوئری نمره‌ای جداگانه دارد و اگر کوئری قسمتی را نتوانستید بنویسید، کوئری‌هایی که حل کردید را بفرستید و کوئری آن قسمت را خالی بگذارید):

  1. آیدی، نام کوچک،‌ فامیلی و نام‌ کاربری تمام کاربرانی که نام کوچک (first_name) آن‌ها با حرف s و فامیلی (last_name) آن‌ها با حرف e تمام می‌شود. کوچک یا بزرگ بودن حروف مهم نیست و رکوردها باید براساس آیدی به صورت صعودی مرتب شوند.
نمونه خروجی کوئری اول

ساختار نتیجه‌ی کوئری و سطر اول آن، به شکل زیر است:

id first_name last_name username
6916 Sarah George patrick32
  1. نام شرکت و مجموعه‌ای از محصولاتی که متعلق به آن شرکت هستند. رکوردها براساس تعداد محصولات شرکت به صورت نزولی مرتب می‌شوند، در صورت برابر بودن تعداد محصولات دو شرکت، ترتیب صعودی آیدی آن‌ها اولویت دارد.
نمونه خروجی کوئری دوم

نمونه خروجی کوئری دوم🔗

ساختار نتیجه‌ی کوئری و سطر اول آن، به شکل زیر است:

company_name product_list
Movies {Hair Care Component,Fitness Equipment,Home Improvement Rig,Truck Item,Furniture Whatchamacallit,Music Widget,Party Gear,Mens Device,Aquarium Instrument,Movie Paraphernalia,Camera Attachment,Skin Care Implement,Makeup Gadget,Party Gadget,Personal Implement,Swimming Rig,Gardening Mechanism,Nutrition Component,Book Machine,Party Mechanism}
  1. در این کوئری باید آدرس شرکتی که کاربر در آن حضور دارد و نام‌ کاربری او را برگردانید. در صورتی که کاربر در شرکتی حضور نداشت یا شرکتی که کاربر در آن حضور دارد، آدرسی نداشت، آدرسی را که در جدول کاربران برای کاربر مشخص‌ شده است، برگردانید. خروجی باید به ترتیب صعودی آیدی کاربران مرتب شده باشد. ترتیب قرار گیری آدرس در ستون user_address به صورت روبرو است: Country, City, Zip Code
نمونه خروجی کوئری سوم

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

username user_address
markbaker Moenstead, Palestine, 4972
garciaamy Murphyton, French Guiana, 5765
jonesandrea Bauchland, Panama, 8125
  1. در این کوئری از شما می‌خواهیم با جست‌و‌جو در جدول محصولات، یک جدول با فیلدها‌ی زیر‌ را برگردانید:
  • نام، قیمت و کتگوری محصول
  • نام و شهرِ شرکت محصول
  • در انتها یک فیلد که در آن اگر قیمت محصول از میانگین قیمت کل محصولات بیش‌تر بود، expensive و اگر قیمت آن از میانگین کل محصولات کم‌تر بود not expensive قرار می‌گیرد.
  • خروجی باید براساس آیدی محصول مرتب شده باشد.
نمونه خروجی کوئری چهارم

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

product_name product_price product_category company_name company_city price_comparison
Bedding Attachment 14 Home Shoes Corkeryland not expensive
Dining Contraption 112 Home Grocery Hartford expensive
Truck Kit 27 Automotive Tools North Burley not expensive

فایل نهایی🔗

پس از پیاده‌سازی کوئری‌ها، آن را در فایل queries.sql، وارد کرده و سپس این فایل را آپلود کنید. کد شما باید به صورت زیر باشد:

-- Section1
   Your first query here
-- Section2
   Your second query here
-- Section3
   Your third query here
-- Section4
   Your fourth query here
SQL

سفر در زمان (سی‌شارپ)


برای این سوال، نسخه‌ی دات‌نت شما باید ۷ باشد.


اندیس

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

شما که از آینده خبر دارید، تصمیم گرفته‌اید سیستم ابتدایی Full-Text Search را پیاده‌سازی کنید. با این اختراع، شما نه تنها دنیای جستجو را متحول می‌کنید بلکه تاریخ را نیز تحت تأثیر قرار خواهید داد و این اختراع را به نام خود ثبت خواهید کرد.

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

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

└── SearchEngine
    ├── Document.cs
    ├── Index.cs
    ├── Program.cs
    ├── Query.cs
    └── SearchEngine.csproj
C#

شما باید سه کلاس Document، Index و Query را مطابق با مواردی که در ادامه مطرح می‌شود، کامل کنید.

کلاس Document🔗

اولین کلاسی که باید تکمیل کنید کلاس Document است. این کلاس بدنه اصلی داکیومنت‌های شما را برای اندیس مشخص می‌کند و باید شامل ویژگی‌های(property) زیر باشد:

نام نوع
Id long
Text string
Date DateTime

کلاس Query🔗

این کلاس شامل ویژگی‌های کوئری است که قصد دارید طبق این ویژگی‌ها داکیومنت‌هایی را از درون اندیس بازیابی کنید. این کلاس شامل ویژگی‌های زیر می‌شود:

نام نوع
Text string
Date DateTime
EndDate DateTime

کلاس Index🔗

این کلاس اصلی‌ترین کلاسی است که باید پیاده‌سازی کنید. این کلاس شامل داکیومنت‌ها و اندیس‌ها می‌شود. اندیس‌های این کلاس در واقعا اندیس‌های معکوس (Inverted index) به هر داکیومنت هستند.

extensionFromNameIndex.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();
    }
}
C#

همان‌طور که می‌بینید، دو اندیس textIndex و dateIndex وجود دارند که نحوه ساخت این اندیس‌ها در ادامه آورده شده است. مطابق این فایل، شما در این کلاس باید یک کانستراکتور و سه متد که در ادامه جزئیات آن‌ها ذکر می‌شود را پیاده‌سازی نمایید:

کانستراکتور Index: این کانستراکتور فایلی که در مسیر ورودی دریافت کرده را به صورت متن خوانده و اندیس‌های گفته شده را باید به درستی مقداردهی کند.

متد saveIndexToFile: این متد یک مسیر را دریافت و کل کلاس Index را با تمام مقادیرش به صورت متن در این مسیر ذخیره می‌کند.

متد indexDocument: این متد یک داکیومنت را دریافت می‌کند و اندیس‌های گفته شده را به صورت زیر ایجاد می‌کند:

  • برای ساخت textIndex باید ویژگی text هر داکیومنت براساس کاراکتر‌های غیر کلمه‌ای (حرف، رقم یا _) شکسته شود و داکیومنت‌ها اندیس شوند.
  • برای ساخت dateIndex هر داکیومنت براساس ویژگی date خودش اندیس می‌شود.

متد search: این متد وظیفه دارد تا داکیومنت‌هایی را براساس کوئری ورودی برگرداند. هر کدام از ویژگی‌های کلاس Query می‌تواند نال باشند ولی در صورتی که هر کدام از مقادیر نال نبود باید داکیومنت‌هایی براساس اولویت زیر برگردانده شوند:

  1. متن
  2. بازه زمانی (این به این معنی است که اگر در کوئری بازه زمانی وارد شده بود، این بازه اولویت بیشتری دارد)
  3. زمان دقیق

مثال🔗

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

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);
C#

خروجی مثال بالا باید داکیومنت‌ها با آی‌دی 1و 2 را برگرداند.

نکات🔗

  • دو کلاس Document و Query باید شامل کانستراکتوری با همه ویژگی‌ها باشند.
  • تضمین می‌شود داکیومنت با آی‌دی تکراری وارد نخواهد شد.
  • دقت کنید که ساختار ابتدایی کلاس‌ها را تغییر ندهید.
  • دقت کنید که کلاس‌های شما در صورت لزوم باید قابلیت سریالایز و دسریالایز شدن داشته باشند.

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

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

[your-solution-file].zip
└── SearchEngine
    ├── Document.cs
    ├── Index.cs
    ├── Program.cs
    ├── Query.cs
    └── SearchEngine.csproj
C#

بانک فناپ


تعریف اولیه🔗

شما مسئول توسعه یک سیستم بانکی ساده تحت وب هستید که شامل چندین قابلیت (Functionality) است. هدف اصلی شما ایجاد و پیاده‌سازی این قابلیت هاست که در ادامه توضیح داده خواهند شد. همچنین یک پروژه اولیه به شما داده شد است که باید تغییرات خود را بر روی آن اعمال نمایید. پروژه اولیه را از این لینک دانلود کنید.

مدل دامنه🔗

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

  • حساب (Account): نمایانگر یک حساب بانکی است که شامل اطلاعاتی مانند شماره حساب، موجودی، شماره شبا و ... است.
  • تراکنش (Transaction): این مدل نمایانگر تراکنش‌های انجام شده برای هر حساب است. اطلاعاتی مانند مبلغ تراکنش، نوع تراکنش (واریز یا برداشت)، تاریخ و ... مرتبط با تراکنش را شامل می‌شود.

اطلاعات مربوط به مدل ها را می توانید در بخش توضیحات ساختار دیتابیس مطالعه بفرمایید


قابلیت های سیستم🔗

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

واحد پولی این سیستم تومان است

قابلیت ۱: مشاهده اطلاعات حساب🔗

سیستم شما باید قادر باشد اطلاعات یک حساب بانکی را نمایش دهد. کاربر با ارائه کد حساب، انتظار دارد اطلاعات مربوط به حساب مورد نظر را دریافت کند.

قالب درخواست🔗
GET https://localhost:7229/api/account/12345
// 12345 --> Account Number
Bash
در صورت موفقیت، پاسخ API به صورت زیر خواهد بود🔗
{
    "number": "12345",
    "sheba": "IR300560611828005221576101",
    "firstName": "علی",
    "lastName": "محمدی",
    "balance": 4880000,
    "creationDate": "2024-10-13"
}
JSON

قابلیت ۲: انجام تراکنش واریز🔗

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

  • ورودی‌ها شامل شماره شبای مقصد، مبلغ واریز و شماره حساب مبدا است
  • مبلغ واریز نباید بزرگتر از موجودی حساب و همچنین سقف روزانه انتقال به مبلغ 200 میلیون تومان باشد در غیر این صورت باید خطایی با متن "عدم رعایت سقف انتقال" دریافت شود.
  • مبلغ تراکنش نمی تواند منفی باشد.
  • قالب داده ای شماره شبا مقصد باید صحیح باشد.
  • حساب مبدا و مقصد نمی تواند برابر باشد، یعنی کاربر نمی تواند از یک حساب، به شبای همان حساب پول واریز کند و در صورت چنین ورودیی باید خطای با متن "حساب مبدا و مقصد نمی تواند یکی باشد" دریافت شود.
  • به ازای هر درخواست واریز، دو تراکنش با کد یکسان (Code) در دیتابیس ذخیره می‌شود، یک تراکنش با تایپ واریز (Deposit) برای حساب مقصد که مبلغ به آن واریز می‌شود و دیگری یک تراکنش با تایپ برداشت (Withdrawal) برای حساب مبدا که مبلغ از آن کسر می‌شود.
  • بعد از ثبت تراکنش، باید اطلاعات موجودی حساب های مبدا و مقصد نیز بروزرسانی شود
فرمت استاندارد شماره شبا

شماره شبا در ایران شامل پیشوند IR و سپس 24 رقم است (مانند: IR300564661822065022536289).

قالب درخواست🔗
POST https://localhost:7229/api/account/12345/deposit

{
    "targetSheba": "IR300560611828005221576101",
    "amount": 120000
}

// 12345 --> Account Number
Bash
در صورت موفقیت، پاسخ API به صورت زیر خواهد بود🔗
{
    "status": "success",
    "newBalance": 10360000,
    "code": "42a74b17-36c4-497a-913e-e675cd13d5e1"
}
JSON

قابلیت ۳: مشاهده لیست تراکنش‌ها🔗

این قابلیت لیستی از تراکنش‌های انجام شده هر حساب را بصورت مرتب شده نزولی بر اساس زمان تراکنش نمایش می دهد. اطلاعات شامل کد تراکنش، مبلغ تراکنش، تاریخ، موجودی بعد از تراکنش، شماره شبای بر روی تراکنش، و نوع تراکنش (واریز یا برداشت) می‌باشد.

قالب درخواست🔗
GET https://localhost:7229/api/account/12345/transactions

// 12345 --> Account Number
Bash
در صورت موفقیت، پاسخ API به صورت زیر خواهد بود🔗
[
  {
    "code": "42a74b17-36c4-497a-913e-e675cd13d5e1",
    "amount": 120000,
    "date": "2024-10-13 12:53",
    "relatedSheba": "IR300564661822065022536289",
    "postBalance": 4880000,
    "type": "Withdrawal"
  }
]
JSON

نکات🔗

  • در توسعه API های سیستم اصول REST را رعایت بفرمایید
  • ورودی ها را ارزیابی کرده و در صورت نامعتبر بودن داده ها خطای مناسب را برگردانید.
  • وضعیت های مشخصی برای هر خطا وجود دارد که توقع می رود در پاسخ درخواست در نظر بگیرید.
    • بررسی داده های ورودی و مسائل بیزینسی 400 (Bad Request)
    • عدم وجود منابع مربوط به داده های ارائه شده 404 (Not Found)
توضیحات ساختار دیتابیس

جدول Accounts:

عنوان نوع توضیحات
Number TEXT (string) شماره حساب منحصر به فرد هر کاربر
Sheba TEXT (string) شماره شبا مرتبط با حساب که منحصر به فرد است
FirstName TEXT (string) نام صاحب حساب
LastName TEXT (string) نام خانوادگی صاحب حساب
Balance REAL (decimal) موجودی حساب
CreationDate TEXT (DateTime) تاریخ ایجاد حساب

جدول Transactions:

عنوان نوع توضیحات
Id INTEGER (int) شناسه منحصر به فرد هر تراکنش
Amount REAL (decimal) مبلغ تراکنش
Code TEXT (string) کد منحصر به فرد تراکنش های مرتبط
Date TEXT (string) تاریخ انجام تراکنش
PostBalance REAL (decimal) موجودی حساب بعد از انجام تراکنش
BaseAccountNumber TEXT (string) شماره حساب مبدا تراکنش
SubAccountNumber TEXT (string) شماره حساب مقصد تراکنش
Type TEXT (TransactionType) نوع تراکنش (واریز یا برداشت)
اطلاعات اولیه دیتابیس

به صورت پیش‌فرض کاربران زیر در دیتابیس تعریف کنید؛ تا برای تست عملکرد برنامه از آنها استفاده کنید.

فرد اول:

  • نام: علی محمدی
  • شماره حساب: 12345
  • شماره شبا: IR300560611828005221576101
  • موجودی اولیه: 5,000,000 ریال

فرد دوم:

  • نام: محمد سلطانی
  • شماره حساب: 32312
  • شماره شبا: IR300564661822065022536289
  • موجودی اولیه: 10,000,000 ریال
آنچه باید آپلود کنید

پاسخ ارسالی شما باید یک فایل zip به همان فرمت پروژه اولیه باشد. در نظر بگیرید که فایل zip شما باید این ساختار فایل را داشته باشد.

├── Banking
│   ├── Banking.csproj
│   ├── Controllers
│   │   └── AccountController.cs
│   ├── Data
│   │   ├── BankingDbContext.cs
│   │   ├── Entities
│   │   │   ├── Account.cs
│   │   │   └── Transaction.cs
│   │   ├── Enums
│   │   │   └── TransactionType.cs
│   │   └── Migrations
│   │       ├── YOUR-MIGRATION-CLASS-HERE
│   │       └── BankingDbContextModelSnapshot.cs
│   ├── Program.cs
│   ├── ViewModels
│   │   ├── AccountResponseVm.cs
│   │   ├── DepositRequestVm.cs
│   │   ├── DepositResponseVm.cs
│   │   └── TransactionResponseVm.cs
│   └── banking.db
└── dotnet-tests.sln
Plain text

در نظر داشته باشید که حتما برای دیتابیس بعد از کانفیگ کردن مدل های خود یک Migration اضافه کنید.

  • مایگریشن ها باید در آدرس : /Data/Migrations قرار گیرد.