Skip to content
Snippets Groups Projects
ServerWithReneges.java 7.70 KiB
/*
 * Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license
 * Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template
 */
package mv3302;

import static java.lang.Double.NaN;
import java.util.SortedSet;
import java.util.TreeSet;
import static simkit.Priority.HIGH;
import simkit.SimEntityBase;
import simkit.random.RandomVariate;

/**
 * Implementation of the multiple server queue model using<code>Customer</code>
 * objects to represent individual customers. This allows the model to
 * explicitly tally measures such as delay in queue and time in system.
 */
public final class ServerWithReneges extends SimEntityBase {

    /**
     * Number of servers (k)
     */
    private int totalNumberServers;

    /**
     * # of available servers (S)
     */
    protected int numberAvailableServers;

    /**
     * Container of waiting customers (q)
     */
    protected SortedSet<Customer> queue;

    /**
     * time a given customer spends in queue (D - a transient state)
     */
    protected double delayInQueueServed = NaN;

    /**
     * time a given customer will spend in the queue before reneging
     */
    private double delayInQueueReneged;

    /**
     * time a given customer spends in the system (W - a transient state)
     */
    protected double timeInSystem = NaN;

    private int numberReneges;

    private int numberServed;

    /**
     * Generates service times ({t<sub>S</sub>})
     */
    private RandomVariate serviceTimeGenerator;

    /**
     * Instantiate a ServerWithReneges with the given totalNumberServers and
     * serviceTimeGenerator. Note: should call <code>this()<</code> to ensure
     * that <code>queue</code> is instantiated
     *
     * @param totalNumberServers
     * @param serviceTimeGenerator
     */
    public ServerWithReneges(int totalNumberServers, RandomVariate serviceTimeGenerator) {
        this();
        setTotalNumberServers(totalNumberServers);
        setServiceTimeGenerator(serviceTimeGenerator);
    }

    /**
     * Instantiate the <code>queue</code>state variable
     */
    public ServerWithReneges() {
        this.queue = new TreeSet<>();
    }

    /**
     * Initialize state variables:<ul>
     * <li>Empty <code>queue</code>
     * <li>set numberAvailableServers to totalNumberServers
     * <li>Set numberServed to 0
     * <li>Set delayInQueue to NaN
     * <li>Set timeInSystem to NaN </ul>
     */
    @Override
    public void reset() {
        super.reset();
        queue.clear();
        numberAvailableServers = getTotalNumberServers();
        delayInQueueServed = NaN;
        delayInQueueReneged = 0.0;
        timeInSystem = NaN;
        numberReneges = 0;
        numberServed = 0;
    }

    /**
     * Fire property changes for time-varying states
     */
    public void doRun() {
        firePropertyChange("queue", getQueue());
        firePropertyChange("numberAvailableServers", getNumberAvailableServers());
        firePropertyChange("numberReneges", getNumberReneges());
    }

    /**
     * Stamp time and add customer to <code>queue</code><br>
     * if available server, schedule StartService with delay of 0.0
     *
     * @param customer Arriving customer
     */
    public void doArrival(Customer customer) {
        customer.stampTime();
        SortedSet<Customer> oldQueue = getQueue();
        queue.add(customer);
        firePropertyChange("queue", oldQueue, getQueue());
        waitDelay("Renege", 0.0, customer);
        if (numberAvailableServers > 0) {
            waitDelay("StartService", 0.0, HIGH);
        }
    }

    /**
     * Decrement numberAvailableServers<br>
     * Remove first customer from <code>queue</code><br>
     * Compute delayInQueueServed as elapsed time<br>
     * Schedule EndService with delay generated by serviceTimeGenerator
     */
    public void doStartService() {
        Customer customer = queue.first();
        SortedSet<Customer> oldQueue = getQueue();
        queue.remove(customer);
        firePropertyChange("queue", oldQueue, getQueue());
        int oldNumberAvailableServers = getNumberAvailableServers();
        numberAvailableServers -= 1;
        firePropertyChange("numberAvailableServers", oldNumberAvailableServers, getNumberAvailableServers());
        delayInQueueServed = customer.getElapsedTime();
        firePropertyChange("delayInQueueServed", getDelayInQueueServed());
        interrupt("Renege", customer);
        waitDelay("EndService", serviceTimeGenerator, customer);
    }

    /**
     * Remove customer from the queue, increment the numberReneges, fires
     * property changes for the total number of reneges, and captures
     * delayInQueueReneged values as elapsedTime
     */
    public void doRenege(Customer customer) {
        delayInQueueReneged = customer.getElapsedTime();
        firePropertyChange("delayInQueueReneged", getDelayInQueueReneged());
        SortedSet<Customer> oldQueue = getQueue();
        queue.remove(customer);
        firePropertyChange("queue", oldQueue, getQueue());
        double oldNumberReneges = getNumberReneges();
        numberReneges += 1;
        firePropertyChange("numberReneges", oldNumberReneges, getNumberReneges());

    }

    /**
     * Increment numberAvailableServers<br>
     * Compute timeInSystem as customer's elapsedTime<br>
     * Increment numberServed<br>
     * If customer(s) in <code>queue</code>, schedule StartService with delay of
     * 0.0
     *
     * @param customer Given customer completing service
     */
    public void doEndService(Customer customer) {
        int oldNumberAvailableServers = getNumberAvailableServers();
        numberAvailableServers += 1;
        firePropertyChange("numberAvailableServers", oldNumberAvailableServers, getNumberAvailableServers());

        timeInSystem = customer.getElapsedTime();
        firePropertyChange("timeInSystem", getTimeInSystem());
        numberServed += 1;
        if (!queue.isEmpty()) {
            waitDelay("StartService", 0.0, HIGH);
        }
    }

    /**
     * @return the totalNumberServers
     */
    public int getTotalNumberServers() {
        return totalNumberServers;
    }

    /**
     * @param totalNumberServers the totalNumberServers to set
     * @throws IllegalArgumentException if totalNumberServers &le; 0
     */
    public void setTotalNumberServers(int totalNumberServers) {
        if (totalNumberServers <= 0) {
            throw new IllegalArgumentException("totalNumberServers must be > 0: " + totalNumberServers);
        }
        this.totalNumberServers = totalNumberServers;
    }

    /**
     * @return the serviceTimeGenerator
     */
    public RandomVariate getServiceTimeGenerator() {
        return serviceTimeGenerator;
    }
    /**
     * @param serviceTimeGenerator the serviceTimeGenerator to set
     */
    public void setServiceTimeGenerator(RandomVariate serviceTimeGenerator) {
        this.serviceTimeGenerator = serviceTimeGenerator;
    }

    /**
     * @return the numberAvailableServers
     */
    public int getNumberAvailableServers() {
        return numberAvailableServers;
    }

    /**
     * @return the queue
     */
    public SortedSet<Customer> getQueue() {
        return new TreeSet<>(queue);
    }

    /**
     * @return the delayInQueue
     */
    public double getDelayInQueueServed() {
        return delayInQueueServed;
    }

    /**
     * @return the timeInSystem
     */
    public double getTimeInSystem() {
        return timeInSystem;
    }

    /**
     * @return the delayInQueueReneged
     */
    public double getDelayInQueueReneged() {
        return delayInQueueReneged;
    }

    public double getNumberReneges() {
        return numberReneges;
    }

    /**
     * @return the numberServed
     */
    public int getNumberServed() {
        return numberServed;
    }

}