jasima.shopSim.core.JobShop Maven / Gradle / Ivy
/*******************************************************************************
* This file is part of jasima, v1.3, the Java simulator for manufacturing and
* logistics.
*
* Copyright (c) 2015 jasima solutions UG
* Copyright (c) 2010-2015 Torsten Hildebrandt and jasima contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see .
*******************************************************************************/
package jasima.shopSim.core;
import jasima.core.simulation.Simulation;
import jasima.core.util.TypeUtil;
import jasima.core.util.observer.NotifierListener;
import jasima.shopSim.core.WorkStation.WorkStationEvent;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Map;
/**
* Implements a shop simulation. Despite its name the scenario not necessarily
* has to be a job shop.
*
* @author Torsten Hildebrandt
* @version
* "$Id: JobShop.java 753 2015-07-27 15:29:49Z [email protected] $"
*/
public class JobShop extends Simulation {
public static class JobShopEvent extends SimEvent {
}
// constants for default events thrown by a shop (in addition to simulation
// events)
public static final JobShopEvent JOB_RELEASED = new JobShopEvent();
public static final JobShopEvent JOB_FINISHED = new JobShopEvent();
// parameters
private int maxJobsInSystem = 0;
private int stopAfterNumJobs = 0;
private boolean enableLookAhead = false;
public JobSource[] sources = {};
public WorkStation[] machines = {};
public Route[] routes = {};
public int jobsFinished;
public int jobsStarted;
// fields used during event notification
public Job lastJobReleased;
public Job lastJobFinished;
public JobShop() {
super();
}
@Override
protected void init() {
super.init();
jobsStarted = jobsFinished = 0;
}
@Override
protected void beforeRun() {
super.beforeRun();
for (WorkStation m : machines)
m.init();
for (JobSource s : sources)
s.init();
}
@Override
protected void done() {
super.done();
for (WorkStation m : machines)
m.done();
}
public void jobFinished(Job j) {
jobsFinished++;
if (getStopAfterNumJobs() > 0 && jobsFinished >= getStopAfterNumJobs()) {
end(); // abort simulation
}
j.jobFinished();
lastJobFinished = j;
if (numListener() > 0)
fire(JOB_FINISHED);
}
public void startJob(Job nextJob) {
nextJob.setJobNum(jobsStarted++);
if (getMaxJobsInSystem() > 0
&& (jobsStarted - jobsFinished) >= getMaxJobsInSystem()) {
print(SimMsgCategory.WARN, "WIP reaches %d, aborting sim.",
getMaxJobsInSystem());
end(); // abort simulation
}
nextJob.jobReleased();
lastJobReleased = nextJob;
if (numListener() > 0)
fire(JOB_RELEASED);
WorkStation mach = nextJob.getCurrentOperation().machine;
mach.enqueueOrProcess(nextJob);
}
@Override
public void produceResults(Map res) {
super.produceResults(res);
res.put("numJobsFinished", jobsFinished);
res.put("numJobsStarted", jobsStarted);
res.put("numWIP", jobsStarted - jobsFinished);
for (WorkStation m : machines) {
m.produceResults(res);
}
}
/**
* Adds a listener to all {@link WorkStation}s in the shop.
*
* @param listener
* The machine listener to add.
* @param cloneIfPossible
* whether to try to clone a new instance for each machine using
* {@link TypeUtil#cloneIfPossible(Object)}.
*/
public void installMachineListener(
NotifierListener listener,
boolean cloneIfPossible) {
for (WorkStation m : machines) {
NotifierListener ml = listener;
if (cloneIfPossible)
ml = TypeUtil.cloneIfPossible(listener);
m.addNotifierListener(ml);
}
}
/**
* Returns the status of lookahead mechanism.
*
* @return Whether lookahead is used.
*/
public boolean isEnableLookAhead() {
return enableLookAhead;
}
/**
* Enable the lookahead mechanism of this shop. If enabled dispatching rules
* can select jobs arriving from in the near future.
*
* @param enableLookAhead
* Whether to enable or disable lookahead.
*/
public void setEnableLookAhead(boolean enableLookAhead) {
this.enableLookAhead = enableLookAhead;
}
/**
* End simulation if WIP (work in process) reaches this value (0: no limit)
*
* @param maxJobsInSystem
* The maximum number of jobs in the system.
*/
public void setMaxJobsInSystem(int maxJobsInSystem) {
this.maxJobsInSystem = maxJobsInSystem;
}
/**
* Returns the maximum number of jobs in the system, before the simulation
* is terminated.
*
* @return The maximum number of jobs in the system.
*/
public int getMaxJobsInSystem() {
return maxJobsInSystem;
}
/**
* End simulation if a certain number of jobs was completed (%lt;=0
* (default): no limit).
*
* @param stopAfterNumJobs
* The number of jobs to finish.
*/
public void setStopAfterNumJobs(int stopAfterNumJobs) {
this.stopAfterNumJobs = stopAfterNumJobs;
}
/**
* Returns the number of jobs to complete before the simulation is ended.
*
* @return The number of jobs to complete before terminating the simulation.
*/
public int getStopAfterNumJobs() {
return stopAfterNumJobs;
}
/**
* Gets the list of job sources in this shop. Do not modify the returned
* array, before manually creating a clone of it.
*
* @return The array of job sources.
*/
public JobSource[] getSources() {
return sources;
}
/**
* Sets all job sources in this shop.
*
* @param sources
* An array with all job sources.
*/
public void setSources(JobSource[] sources) {
this.sources = sources.clone();
int i = 0;
for (JobSource js : sources) {
js.setShop(this);
js.index = i++;
}
}
public void addJobSource(JobSource js) {
ArrayList list = new ArrayList(
Arrays.asList(sources));
list.add(js);
js.setShop(this);
js.index = list.size() - 1;
sources = list.toArray(new JobSource[list.size()]);
}
public void removeJobSource(JobSource js) {
ArrayList list = new ArrayList(
Arrays.asList(sources));
if (list.remove(js)) {
js.setShop(null);
js.index = -1;
int i = 0;
for (JobSource s : list) {
s.index = i++;
}
sources = list.toArray(new JobSource[list.size()]);
}
}
/**
* Gets the list of workstations in this shop. This returns method returns
* the internal array, so do not modify it externally.
*
* @return An array of all workstations of this shop.
*/
public WorkStation[] getMachines() {
return machines;
}
/**
* Sets the workstations of this shop.
*
* @param machines
* An array containing all workstations for this shop.
*/
public void setMachines(WorkStation[] machines) {
this.machines = machines.clone();
int i = 0;
for (WorkStation w : machines) {
w.shop = this;
w.index = i++;
}
}
/**
* Adds a single machine to this shop.
*
* @see #getMachines()
* @param machine
* The workstation to add.
*/
public void addMachine(WorkStation machine) {
ArrayList list = new ArrayList(
Arrays.asList(machines));
list.add(machine);
machine.shop = this;
machine.index = list.size() - 1;
machines = list.toArray(new WorkStation[list.size()]);
}
/**
* Removes a machine from this shop.
*
* @param machine
* The workstation to remove.
*/
public void removeMachine(WorkStation machine) {
ArrayList list = new ArrayList(
Arrays.asList(machines));
if (list.remove(machine)) {
machine.shop = null;
machine.index = -1;
int i = 0;
for (WorkStation w : list) {
w.index = i++;
}
machines = list.toArray(new WorkStation[list.size()]);
}
}
/**
* Returns a workstation with the given name, or {@code null} if no such
* workstation exists.
*
* @param name
* The workstation's name.
* @return The workstation with the given name, if it exists. {@code null}
* otherwise.
*/
public WorkStation getWorkstationByName(String name) {
WorkStation res = null;
if (getMachines() != null)
for (WorkStation w : getMachines()) {
if (name.equals(w.getName())) {
res = w;
break; // for w
}
}
return res;
}
/**
* Returns the routes added to this job shop. Do not modify externally.
*
* @return An array of all routes in this shop.
*/
public Route[] getRoutes() {
return routes;
}
/**
* Sets the routes available for this job shop.
*
* @param routes
* The route list.
*/
public void setRoutes(Route[] routes) {
this.routes = routes.clone();
}
public void addRoute(Route r) {
ArrayList list = new ArrayList(Arrays.asList(routes));
list.add(r);
routes = list.toArray(new Route[list.size()]);
}
public void removeRoute(Route r) {
ArrayList list = new ArrayList(Arrays.asList(routes));
if (list.remove(r)) {
routes = list.toArray(new Route[list.size()]);
}
}
}