سلام دوست عزیز😃👋

به مسابقه «مسابقه رایان‌کد» خوش آمدی!

هرگونه ارتباط با سایر شرکت‌کنندگان و یا استفاده از ابزارهای تولید کد، مثل chatGPT و... در مسابقات کوئرا ممنوع است و بعد از شناسایی از لیست شرکت‌کنندگان مسابقه حذف می‌شوید.

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

سوالات و مشکلات خودتان را می‌توانید از طریق قسمت «سوال بپرسید» با ما در میان بگذارید.

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

موفق باشید و بهتون خوش بگذره 😉✌

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


در آستانه‌ی زمستان، از شما می‌خواهیم سیستم الکترونیکی یک بخاری برقی را طراحی کنید که در حالت‌های مختلف می‌تواند عمل کند و در شرایط هم‌روند (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 را در قالب یک فایل زیپ آپلود کنید. انتظار می‌رود باقی فایل‌ها را تغییر ندهید و می‌توانید فرض کنید که همین فایل‌ها به همین شکل در زمان اجرای پروژه نیز در کنار برنامه‌ی شما موجودند.

ارسال پاسخ برای این سؤال
در حال حاضر شما دسترسی ندارید.