ارزش سهام در روز


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

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

توضیح تصویر

حال، از شما خواسته شده است برنامه‌ای بنویسید که تعداد دفعات تکرار عبارت RayanCode (بدون در نظر گرفتن بزرگ یا کوچک بودن حروف) را در میان nn رشته‌ای که در ورودی دریافت می‌کنید، محاسبه کند.

ورودی🔗

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

1n10001 \leq n \leq 1000

در nn سطر بعدی، هر خط شامل یک رشته از حروف کوچک و بزرگ انگلیسی است که طول آن حداکثر 100100 کاراکتر است.

خروجی🔗

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

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

6
RayanCode
RayanCup
JavaRayan
rayanCode
RAYANCODE
rayancode
Plain text

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

4
Plain text

رشته‌های اول (RayanCode)، چهارم (rayanCode)، پنجم (RAYANCODE) و ششم (rayancode) باید شمارش شوند. بنابراین پاسخ 44 است.

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

10
R
Ra
Ray
Raya
Rayan
RayanC
RayanCo
RayanCod
RayanCode
RayanCodes
Plain text

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

1
Plain text

فقط رشته‌ی RayanCode باید شمارش شود. بنابراین پاسخ 11 است.

میانگین وزن‌دار متحرک


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

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

توضیح تصویر

فرض کنید ارزش سهام رایان‌کد در شهر رایان در nn روز مختلف به‌ترتیب a1,a2,,ana_1, a_2, \dots, a_n باشد. همچنین عدد صحیح و مثبت kk به‌عنوان بازه‌ی زمانی مشخص شده است.

برای هر kk روز متوالی به ترتیب میانگین ورزن‌دار ارزش سهام در آن kk روز را حساب می‌کنیم. برای وزن‌دادن به ترتیب از اعداد 11 تا kk برای روزها استفاده می‌کنیم و وزن‌ها را به‌ترتیب صعودی برای ارزش سهام‌ها از قدیم به جدید در نظر می‌گیریم.

برای مثال اگر n=7n = 7 و k=4k = 4 و ارزش سهام‌ها به‌صورت زیر باشد: [100,200,100,100,300,200,500][100, 200, 100, 100, 300, 200, 500]

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

1×100+2×200+3×100+4×1001+2+3+4=120\frac{1 \times 100 + 2 \times 200 + 3 \times 100 + 4 \times 100}{1 + 2 + 3 + 4} = 120

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

ورودی🔗

در سطر اول، دو عدد صحیح مثبت nn و kk داده می‌شود که تعداد روزها و بازه زمانی را مشخص می‌کند. 1kn1000001 \leq k \leq n \leq 100 \, 000

در سطر دوم ورودی، nn عدد صحیح که با یک فاصله از هم جداشده‌اند آمده و عدد iiام نشان دهنده‌ی ارزش سهام در روز iiام است.

1ai10000001 \leq a_i \leq 1000 \, 000

خروجی🔗

در nk+1n - k + 1 سطر، مقادیر میانگین وزن‌دار متحرک برای هر بازه زمانی چاپ کنید. پاسخ شما زمانی پذیرفته می‌شود که اختلافش با جواب صحیح، حداکثر 10310^{-3} باشد.

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

7 4
100 200 100 100 300 200 500
Plain text

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

120.000000000
190.000000000
200.000000000
330.000000000
Plain text

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

3 1
1 2 3
Plain text

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

1.000000000
2.000000000
3.000000000
Plain text

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

4 2
8 3 6 3
Plain text

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

4.666666667
5.000000000
4.000000000
Plain text

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

3 3
1 2 3
Plain text

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

2.333333333
Plain text

تحلیل ارزش سهام


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

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

توضیح تصویر

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

به‌طور دقیق‌تر فرض کنید در روز kkام هستیم و ارزش سهام در روزهای 1,2,,k1, 2, \dots, k را می‌دانیم. می‌خوهیم از روی ارزش‌ها برای روز kkام تصمیم بگیریم.

مقدار avg_max_halfavg\_max\_half را برابر میانگین k2\lceil\frac{k}{2}\rceil بزرگ‌ترین اعداد بین a1,a2,,aka_1, a_2, \dots, a_k است.

مقدار avg_min_halfavg\_min\_half را برابر میانگین k2\lceil\frac{k}{2}\rceil کوچک‌ترین اعداد بین a1,a2,,aka_1, a_2, \dots, a_k است.

برای تصمیم گیری در روز kkام اگر

  • مقدار aka_k بزرگ‌تر اکید از avg_max_halfavg\_max\_half بود، این سهام را می‌خریم.
  • مقدار aka_k کوچک‌تر اکید از avg_min_halfavg\_min\_half بود، این سهام را می‌فروشیم.
  • هیچ‌کدام از دو حالت بالا نبود دست نگه می‌داریم.

حال از شما می‌خواهیم برنامه‌ای بنویسید که تصمیم ما در روزهای k=1,2,,nk = 1, 2, \dots, n را مشخص کند.

ورودی🔗

در سطر اول ورودی، عدد صحیح nn آمده که تعداد روزها را نشان می‌دهد. 1n1000001 \leq n \leq 100 \, 000

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

1ai1091 \leq a_i \leq 10^9

خروجی🔗

برای هر روز یک رشته برابر HOLD، SELL یا BUY را چاپ کنید.

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

4
71 35 89 12
Plain text

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

HOLD
HOLD
BUY
SELL
Plain text

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

8
70 50 20 40 80 60 10 30
Plain text

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

HOLD
HOLD
SELL
HOLD
BUY
HOLD
SELL
HOLD
Plain text

پرداخت‌ها و حساب‌های بانکی


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

توضیح تصویر

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

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

پروژه اولیه🔗

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

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

init.zip
├── Account.java
├── Payment.java
├── CreditCardPayment.java
├── DigitalWalletPayment.java
├── CashPayment.java
└── Main.java
Plain text

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

کلاس Account🔗

کلاس Account نمایانگر یک حساب بانکی است. هر حساب دارای نام و موجودی است. همچنین، می‌توان موجودی حساب را بررسی کرده و واریز یا برداشت از آن انجام داد. در این کلاس باید امکان برداشت از حساب‌ها و مدیریت موجودی را داشته باشد. همچنین، در صورت تلاش برای برداشت بیشتر از موجودی، خطای کمبود موجودی به کاربر نمایش داده می‌شود.

کلاس Payment🔗

کلاس Payment یک کلاس انتزاعی است که روش‌های پرداخت مختلف از جمله پرداخت با کارت اعتباری، کیف پول دیجیتال و پرداخت نقدی از آن ارث می‌برند. این کلاس متدی به نام processPayment() دارد که فرایند هر پرداخت را انجام ‌می‌دهد.

پرداخت‌ها🔗

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

  • پرداخت با کارت اعتباری (CreditCardPayment): این کلاس باید اطلاعات مربوط به کارت اعتباری را نگهداری کرده و عملیات برداشت از حساب و واریز به حساب مقصد را انجام دهد.
  • پرداخت با کیف پول دیجیتال (DigitalWalletPayment): این کلاس باید اطلاعات مربوط به کیف پول دیجیتال و ایمیل صاحب کیف پول را نگهداری کرده و مانند پرداخت کارت اعتباری، عملیات مالی را انجام دهد.
  • پرداخت نقدی (CashPayment): این کلاس باید میزان مبلغ نقدی را مشخص کرده و مشابه دو نوع دیگر، پرداخت را انجام دهد.

جزئیات پیاده‌سازی این سه کلاس در ادامه آورده شده است.

توضیحات کلاس CreditCardPayment‍

پرداخت با کارت اعتباری باید شامل ویژگی‌ها و متدهای زیر باشد:

  • sourceAccount: حساب مبدا که پرداخت از آن انجام می‌شود.
  • destinationAccount: حساب مقصد که پرداخت به آن انجام می‌شود.
  • amount: مبلغ پرداخت.

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

public CreditCardPayment(Account sourceAccount, Account destinationAccount, int amount)
Java

این سازنده باید ویژگی‌های کلاس را مقداردهی کند.

متد processPayment() باید بررسی کند که حساب مبدا موجودی کافی برای پرداخت دارد. اگر موجودی کافی بود، مبلغ مشخص‌شده را از حساب مبدا کم کند و مبلغ را به حساب مقصد واریز کند. در صورت موفقیت‌آمیز بودن پرداخت، پیام

Credit card payment processed: {amount}
Plain text

برگردانده شود که در آن {amount}، یک عدد است که مقدار تراکنش را نشان می‌دهد.

همچنین اگر موجودی کافی نبود، پیغام خطای زیر را برگرداند:

Insufficient funds in account: {accountName}
Plain text
توضیحات کلاس DigitalWalletPayment

پرداخت با کیف پول دیجیتال باید شامل ویژگی‌ها و متدهای زیر باشد:

  • sourceAccount: حساب مبدا که پرداخت از آن انجام می‌شود.
  • destinationAccount: حساب مقصد که پرداخت به آن انجام می‌شود.
  • walletName: نام کیف پول دیجیتال.
  • email: ایمیل صاحب کیف پول دیجیتال.
  • amount: مبلغ پرداخت.

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

public DigitalWalletPayment(Account sourceAccount, Account destinationAccount, String walletName, String email, int amount)
Java

این سازنده باید ویژگی‌های کلاس را مقداردهی کند.

متد processPayment() باید بررسی کند که حساب مبدا موجودی کافی برای پرداخت دارد. اگر موجودی کافی بود مبلغ مشخص‌شده را از حساب مبدا کم کند و مبلغ را به حساب مقصد واریز کند. سپس یک پیام موفقیت به صورت زیر برگرداند:

Payment of {amount} processed via {walletName} for {email}.
Plain text

و اگر موجودی کافی نبود، پیغام خطای زیر را برگرداند:

Insufficient funds in account: {accountName}
Plain text
توضیحات کلاس CashPayment

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

  • sourceAccount: حساب مبدا که پرداخت از آن انجام می‌شود.
  • destinationAccount: حساب مقصد که پرداخت به آن انجام می‌شود.
  • amount: مبلغ پرداخت.

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

public CashPayment(Account sourceAccount, Account destinationAccount, int amount)
Java

این سازنده باید ویژگی‌های کلاس را مقداردهی کند.

متد processPayment() باید بررسی کند که حساب مبدا موجودی کافی برای پرداخت دارد. اگر موجودی کافی بود، مبلغ مشخص‌شده را از حساب مبدا کم کند، مبلغ را به حساب مقصد واریز کند و یک پیام موفقیت به صورت زیر برگرداند:

Cash payment of {amount} completed.
Plain text

اگر موجودی کافی نبود، پیغام خطای زیر را برگرداند:

Insufficient funds in account: {accountName}
Plain text

پس از پیاده‌سازی کامل، مطمئن شوید که برنامه شما تست می‌شود و تمامی سناریوها (مانند موفقیت در پرداخت یا خطای کمبود موجودی) به درستی مدیریت شده‌اند.

نکات🔗

  • کد شما باید از اصول شی‌گرایی و مدیریت خطا برای پیاده‌سازی انواع مختلف پرداخت‌ها و حساب‌ها استفاده کند.
  • برای هر کلاس متد‌های get و set برای دسترسی به ویژگی‌های آن‌ها ایجاد کنید.
  • در صورتی که کاربر سعی کند مبلغی بیشتر از موجودی خود برداشت کند، باید پیغام خطای مناسب چاپ شود.
  • از طراحی کد به‌گونه‌ای استفاده کنید که به‌راحتی بتوانید انواع جدید پرداخت‌ها را به سیستم اضافه کنید.
  • تمام این کلاس‌های پرداخت باید از کلاس انتزاعی Payment ارث‌بری کنند و متد processPayment() را پیاده‌سازی نمایند.
  • برای مدیریت حساب‌ها، از متدهای موجود در کلاس Account برای برداشت و واریز استفاده کنید.

نمونه🔗

در زیر نمونه‌ای از نحوه استفاده از کلاس‌ها برای انجام پرداخت‌ها آورده شده است:

extensionFromNameMain.java
package org.example.solution;

public class Main {
    public static void main(String[] args) {
        Account account1 = new Account("Ali", 1000);
        Account account2 = new Account("Sara", 2000);

        System.out.println(account1.logBalance());
        System.out.println(account2.logBalance());

        Payment[] payments = new Payment[]{
                new CreditCardPayment(account1, account2, 500),
                new DigitalWalletPayment(account2, account1, "wallet1", "email@email.com", 300),
                new CashPayment(account1, account2, 900) // این پرداخت باید خطای کمبود موجودی بدهد
        };

        for (Payment payment : payments) {
            System.out.println(payment.processPayment());
        }

        System.out.println(account1.logBalance());
        System.out.println(account2.logBalance());
    }
}
Java

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

Account: Ali, Balance: 1000
Account: Sara, Balance: 2000
Credit card payment processed: 500
Payment of 300 processed via wallet1 for email@email.com.
Insufficient funds in account: Ali
Account: Ali, Balance: 800
Account: Sara, Balance: 2200
Plain text

آن‌چه باید ارسال کنید🔗

پس از پیاده‌سازی سیستم، تنها فایل‌های کلاس‌های پیاده‌سازی‌شده را در قالب یک فایل فشرده ارسال کنید. از درج کردن package در فایل‌ها پرهیز کنید. انتظار می‌رود باقی فایل‌ها را تغییر ندهید و می‌توانید فرض کنید که همین فایل‌ها به همین شکل در زمان اجرای پروژه نیز در کنار برنامه‌ی شما موجودند.

[your-solution-files-name].zip
├── CreditCardPayment.java
├── DigitalWalletPayment.java
└── CashPayment.java
Plain text

بخاری هم‌روند


در آستانه‌ی زمستان، از شما می‌خواهیم سیستم الکترونیکی یک بخاری برقی را طراحی کنید که در حالت‌های مختلف می‌تواند عمل کند و در شرایط هم‌روند (concurrent) عملکرد مناسبی دارد!

توضیح تصویر

این بخاری تنها یک دکمه دارد که قابل کلیک کردن توسط کاربر است و به واسطه‌ی آن کاربر می‌تواند آن را روشن کند (ON)، خاموش کند (OFF) و یا به حالت کم مصرف ببرد (DIM). با کلیک کردن بر روی دکمه‌ی بخاری، بخاری به حالت بعدی می‌رود. هر بخاری در زمان ساخت لیستی از حالت‌های عملکردی را در قالب یک آرایه دریافت می‌کند و در زمان کلیک شدن بر روی دکمه به حالت بعدی می‌رود.

برای کلیک کردن روی دکمه، دو حالت خاص وجود دارد.

  • حالت خاص اول حالتی است که کاربر با فاصله‌ی بسیار کم از کلیک کردن قبلی مجدد کلیک کند. این حالت از این نظر حائز اهمیت است که دکمه‌ی بخاری به گونه‌ای طراحی شده که با نگه داشتن آن سیگنال کلیک چندین بار به برد اصلی ارسال می‌شود. در این حالت باید تنها اولین کلیک در نظر گرفته شود و باقی کلیک‌ها در نظر گرفته نشوند.
  • حالت خاص دوم زمانی است که کاربر در زمان روشن (ON و یا DIM) پس از مدت خیلی زیادی اقدام به کلیک کردن دکمه کند. در این حالت فرض می‌شود که کاربر به سادگی می‌خواهد بخاری را خاموش کند و نمی‌خواهد حالت آن را تغییر دهد. برای این حالت، مطلوب این است که بخاری به حالت خاموش برود.

این بخاری برای تامین انرژی خود به یک منبع تغذیه نیاز دارد که این منبع تغذیه قابلیت تامین انرژی با توان‌های متفاوت را دارد و تنها کافی است که بخاری مقدار توان مورد نیاز خود را به آن اعلام کند. بخاری به ازای هر حالت می‌داند که به چه توانی نیاز دارد و به همین ترتیب می‌تواند بر اساس حالت کنونی‌اش مقدار توان مورد نیاز خود را به منبع تغذیه اعلام کند.

پس از ساخت مدار بخاری، برای ارزیابی آن در حالت‌های خاص شما متوجه می‌شوید که به یک ابزار کمکی نیاز دارید تا سناریوهای متفاوت را بتواند به راحتی شبیه‌سازی کند. هدف اصلی این شبیه‌ساز، بررسی صحت جا به جا شدن بین حالت‌های مختلف با وارد کردن تعداد کلیک‌های همزمان در زمان‌های مختلف است. مثلا یک سناریو می‌تواند به این شکل باشد که: ۳ کلیک در زمان t=100mst=100ms و سپس ۱۰ کلیک در زمان t=400mst=400ms که انتظار داریم کلیک‌های اول از حالت خاموش به روشن و کلیک‌های دوم بخاری را از حالت روشن به حالت کم مصرف تغییر حالت دهند.

کلاس‌ها🔗

پیاده‌سازی این سوال در قالب چندین کلاس انجام می‌شود که شما باید آن‌ها را پیاده‌سازی کنید. در این قسمت هر کلاس به شکل جداگانه توضیح داده می‌شود.

کلاس Heater🔗

import java.time.Duration;

public class Heater {
    private final Mode[] modes;
    private final Duration timeout;
    private final Duration closeThreshold;
    private final PowerSource powerSource;

    public Heater(Mode[] modes, Duration timeout, Duration closeThreshold, PowerSource powerSource) {
        // TODO
    }

    public void click() {
        // TODO
    }

    public Mode getCurrentMode() {
        // TODO
    }
}
Java

این کلاس اولین کلاسی است که باید پیاده‌سازی کنید. برای پیاده‌سازی این کلاس لازم است سه متد شامل‌ «سازنده»، «کلیک» و «گرفتن وضعیت فعلی» را پیاده‌سازی کنید.

  • سازنده: این کلاس تنها یک سازنده دارد که در آن باید معتبر بودن آرایه‌ی modes را بررسی کنید و ویژگی‌های کلاس را مطابق نیاز مقداردهی کنید.
  • کلیک: متد کلیک وظیفه اعمال سیگنال کلیک را بر عهده دارد. در نتیجه‌ی اجرای این تابع باید (در صورت نیاز) حالت کنونی بخاری عوض شود و این موضوع به منبع تغذیه هم اعلام شود. همچنین مهم است که این متد به شکل ترد-سیف پیاده‌سازی شود چرا که ممکن است تعداد زیادی سیگنال کلیک به شکل هم‌روند دریافت شوند.

اعتبارسنجی حالت‌ها🔗

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

  • همه‌ی اعضای آرایه باید غیر null باشند.
  • عضو تکراری مجاز است اما دو عضو پشت سر هم نباید تکراری باشند.
  • وضعیت OFF تنها یک بار و آن هم دقیقا در اول آرایه مجاز است.
  • طول‌ آرایه باید حداقل ۲ باشد. (یک حالت روشن یا نیمه روشن و یک حالت خاموش)

اینام Mode🔗

برای بازنمایی حالت‌های مختلف کارکردی بخاری از یک اینام استفاده شده است. این اینام سه حالت متفاوت دارد که شامل روشن و خاموش و کم‌مصرف هستند. با استفاده از متد getPowerConsumption می‌توانید به توان مصرفی بخاری در هر یک از حالت‌ها دست پیدا کنید که برای تنظیم منبع تغذیه ضروری است.

public enum Mode {
    OFF("Heater is off", 0),
    ON("Heater is on", 100),
    DIM("Heater is dimmed", 50);

    private final String description;
    private final int powerConsumption;

    Mode(String description, int powerConsumption) {
        this.description = description;
        this.powerConsumption = powerConsumption;
    }

    public String getDescription() {
        return this.description;
    }

    public int getPowerConsumption() {
        return this.powerConsumption;
    }
}
Java

اینترفیس PowerSource🔗

public interface PowerSource {
    void set(int amount);
}
Java

این اینترفیس یک متد دارد که مقدار توان مصرفی را دریافت می‌کند. این اینترفیس پیاده‌سازی‌های مختلفی بسته به تست دارد که برای اطمینان از کارکرد صحیح بخاری استفاده می‌شوند. همچنین یک پیاده‌سازی ساده‌ی آن نیز همراه با تست‌های نمونه در اختیار شما قرار گرفته است. نکته قابل توجه این است که نباید با مقدار تکراری متدset صدا زده شود و تنها زمانی مجاز به صدا کردن این متد هستید که یک مقدار (amount) جدید (متفاوت با قبلی) برای تنظیم کردن داشته باشید.

کلاس Simulator🔗

import java.time.*;
import java.util.*;

public class Simulator {
    public static record Event(Instant time, int clickCount, Mode oldMode, Mode newMode) {}
    public static enum Strategy {
        THREAD_POOL,
        THREAD,
        SEQUENTIAL;
    }

    private final Heater heater;
    private final List<Event> events;
    private final Strategy strategy;

    public Simulator(Heater heater, Strategy strategy, List<Event> events) {
        // TODO
    }

    public boolean run() {
        // TODO
    }
}
Java

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

رکورد Event🔗

این رکورد برای نگهداری یک رویداد کلیک کردن استفاده می‌شود. یک رویداد شامل یک زمان است که با یک شی از نوع Instant نگهداری می‌شود. همچنین یک عدد شامل تعداد کلیک‌های همزمان نیز دریافت می‌شود که مشخص می‌کند در زمان معین چه تعداد بار باید متد کلیک صدا زده شود. در ادامه دو حالت وضعیت نیز دریافت می‌شود که وضعیت قبل از کلیک و وضعیت بعد از کلیک را مشخص می‌کند. این وضعیت‌ها در زمان اجرای شبیه‌سازی باید با وضعیت واقعی (actual) بخاری تطبیق داده شوند تا دقیقا برابر هم باشند.

اینام Strategy🔗

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

  • ساده‌ترین مکانیسم به شکل SEQUENTIAL است که در این حالت هیچ ترد جدیدی ساخته نمی‌شود و همه‌ی عملیات در همان ترد main انجام می‌شود.
  • مکانیسم بعدی با کمک THREADهاست که برای هر عملیات کلیک یک ترد مجزا ساخته می‌شود تا در زمان معین متد کلیک را اجرا کند.
  • در نهایت مکانیسم آخر با کمک THREAD_POOL است. در این روش با کمک یک تردپول، تسک‌های مورد نظر ساخته و سابمیت می‌شوند. در این روش تعداد تردهای تردپول را برابر عدد ۵ (به شکل ثابت) بگذارید تا بیشتر از این ترد ساخته نشود.

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

متد run🔗

این متد، متد اصلی شبیه‌ساز است که شبیه‌سازی را بسته به استراتژی انتخاب شده اجرا می کند. این متد یک خروجی از نوع boolean دارد که نشان می‌دهد آیا شبیه‌سازی مطابق انتظار پیش رفت یا خیر. به بیان دیگر اگر همه‌ی فرضیات «حالت قدیمی» و «حالت جدید»ها درست از آن در آمده باشند (که به معنی پیاده‌سازی صحیح بخاری است) مقدار true و در غیر این صورت مقدار false برمیگردد.

پروژه اولیه🔗

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

initial.zip
├── Heater.java
├── InvalidModesException.java
├── Mode.java
├── PowerSource.java
├── SampleTest.java
└── Simulator.java
Plain text

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

پس از پیاده‌سازی و اجرای تست نمونه (موجود در فایل SampleTest.java)، فایل ‌های Heater.java و Simulator.java را در قالب یک فایل زیپ آپلود کنید. انتظار می‌رود باقی فایل‌ها را تغییر ندهید و می‌توانید فرض کنید که همین فایل‌ها به همین شکل در زمان اجرای پروژه نیز در کنار برنامه‌ی شما موجودند.