jasima.shopSim.core.Job 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.util.ValueStore;
import jasima.core.util.observer.Notifier;
import jasima.core.util.observer.NotifierAdapter;
import jasima.core.util.observer.NotifierListener;
import jasima.shopSim.core.Job.JobEvent;
import java.util.Collections;
import java.util.HashMap;
import java.util.Set;
/**
* Main work unit in a shop.
*
* @author Torsten Hildebrandt
* @version "$Id: Job.java 753 2015-07-27 15:29:49Z [email protected] $"
*/
// TODO: PrioRuleTarget should be an interface
public class Job extends PrioRuleTarget implements Cloneable,
Notifier, ValueStore {
/** Base class for workstation events. */
public static class JobEvent {
}
// constants for events thrown by a job
public static final JobEvent JOB_RELEASED = new JobEvent();
public static final JobEvent JOB_FINISHED = new JobEvent();
public static final JobEvent JOB_ARRIVED_IN_QUEUE = new JobEvent();
public static final JobEvent JOB_REMOVED_FROM_QUEUE = new JobEvent();
public static final JobEvent JOB_START_OPERATION = new JobEvent();
public static final JobEvent JOB_END_OPERATION = new JobEvent();
private final JobShop shop;
private double arriveTime; // arrival time at current machine
private WorkStation currMachine;
// when will job finish processing on its current machine (if started)
private double startTime;
private double finishTime;
private double relDate;
private double dueDate;
private int jobNum; // global number of job in system
private int jobType;
private double weight = 1.0d;
private int taskNumber; // current operation
private Operation[] ops;
private double[] opDueDates;
private boolean isFuture = false;
private String name = null;
private Route route = null;
// we cache the value returned by remainingProcTime()
private double remProcTime = -1.0d;
private Job future;
public Job(JobShop shop) {
super();
this.shop = shop;
}
public void setArriveTime(double fl) {
arriveTime = fl;
}
public double getArriveTime() {
return arriveTime;
}
public void setJobType(int job) {
jobType = job;
}
public int getJobType() {
return jobType;
}
public void setTaskNumber(int tn) {
remProcTime = -1.0d;
taskNumber = tn;
}
public int getTaskNumber() {
return taskNumber;
}
public void setCurrMachine(WorkStation currMachine) {
this.currMachine = currMachine;
}
public WorkStation getCurrMachine() {
return currMachine;
}
public Operation getCurrentOperation() {
return ops[taskNumber];
}
public double currProcTime() {
return ops[taskNumber].procTime;
}
public double procSum() {
double res = 0d;
for (Operation o : ops) {
res += o.procTime;
}
return res;
}
public double remainingProcTime() {
if (remProcTime < 0.0d) {
remProcTime = 0f;
Operation[] ops = this.ops;
for (int i = taskNumber; i < ops.length; i++) {
remProcTime += ops[i].procTime;
}
}
return remProcTime;
}
public int numOps() {
return getOps().length;
}
public int numOpsLeft() {
return getOps().length - getTaskNumber();
}
/**
* If the this job has one or more tasks yet to be done, send the job to the
* next machine on its route
*/
void proceed() {
if (!isLastOperation()) {
setTaskNumber(getTaskNumber() + 1);
WorkStation mNext = ops[taskNumber].machine;
mNext.enqueueOrProcess(this);
} else {
shop.jobFinished(this);
}
}
void jobReleased() {
fire(JOB_RELEASED);
}
void jobFinished() {
fire(JOB_FINISHED);
}
void arriveInQueue(WorkStation workStation, double arrivesAt) {
setCurrMachine(workStation);
setArriveTime(arrivesAt);
fire(JOB_ARRIVED_IN_QUEUE);
}
void removedFromQueue() {
fire(JOB_REMOVED_FROM_QUEUE);
}
void startProcessing() {
setFinishTime(currMachine.currMachine.procFinished);
setStartTime(currMachine.shop().simTime());
notifyNextMachine();
fire(JOB_START_OPERATION);
}
void endProcessing() {
fire(JOB_END_OPERATION);
}
/**
* Notify next machine of future arrival. This mehod is called whenever an
* operation is started. This method assumes isFinished to be set to the
* correct value before this method is called.
*/
public void notifyNextMachine() {
if (!isLastOperation() && shop.isEnableLookAhead()) {
final Job f = getMyFuture();
final WorkStation next = f.ops[f.taskNumber].machine;
next.futureArrival(f, getFinishTime());
}
}
/**
* Returns a clone of this Job switched to the next operation.
*
* @return The future clone of this job.
*/
public Job getMyFuture() {
if (future == null) {
future = silentClone();
future.setFuture(true);
}
future.setTaskNumber(taskNumber + 1);
return future;
}
@SuppressWarnings("unchecked")
@Override
public Job clone() throws CloneNotSupportedException {
Job j = (Job) super.clone();
j.future = null;
if (valueStore != null) {
j.valueStore = (HashMap