package jamel.basicModel.firms;
import java.util.List;
import jamel.Jamel;
import jamel.util.AgentDataset;
import jamel.util.BasicTimer;
import jamel.util.JamelObject;
import jamel.util.Timer;
/**
* A very basic factory.
*/
class BasicFactory extends JamelObject implements Factory {
/**
* The number of machines.
*/
private final int capacity = 10;
/**
* The dataset.
*/
private final AgentDataset dataset;
/**
* The heap of product.
*/
private final BasicGoods finishedGoods = new BasicGoods();
/**
* Inventories of unfinished and finished goods, in volume.
*/
private final int[] materials = new int[this.productionProcessLenght];
/**
* A flag that indicates whether this factory is open or not.
*/
private boolean open = false;
/**
* Length of the production process.
*/
private final int productionProcessLenght = 6;
/**
* The productivity of one worker/machine.
*/
private final int productivity = 100;
/**
* The timer of the factory.
*/
private final Timer timer;
/**
* Inventories of unfinished and finished goods, in value.
*/
private final long[] values = new long[this.productionProcessLenght];
/**
* Creates a new basic factory.
*
* @param firm
* the parent firm.
*/
public BasicFactory(BasicFirm firm) {
super(((JamelObject) firm).getSimulation());
this.dataset = firm.getDataset();
this.timer = new BasicTimer(this.getSimulation().getPeriod());
}
/**
* Closes the factory at the end of the period.
*/
@Override
public void close() {
if (!this.open) {
throw new RuntimeException("Already closed.");
}
this.open = false;
}
@Override
public double getCapacity() {
return this.capacity;
}
@Override
public Goods getInventories() {
return this.finishedGoods;
}
@Override
public long getValue() {
long result = this.finishedGoods.getValue();
for (int i = 0; i < this.values.length; i++) {
result += this.values[i];
}
return result;
}
/**
* Opens the factory at the beginning of the period.
*/
@Override
public void open() {
if (this.open) {
throw new RuntimeException("Already open.");
}
this.timer.next();
if (this.timer.getValue() != this.getPeriod()) {
throw new RuntimeException("Not synchronized.");
}
if (!this.finishedGoods.isEmpty()) {
throw new RuntimeException("The heap of product should be empty at the beginning of the period.");
// TODO Ah ben ça alors ! Ca m'étonnerait fort !
}
this.open = true;
}
@Override
public void production(final List<? extends LaborContract> contracts) {
// Encapsulates the production process.
// TODO vérifier (1) factory is open (2) used only once by period
// TODO vérifier le fonctionnement de cette méthode en la traçant.
if (contracts.size() > this.capacity) {
Jamel.println();
Jamel.println("contracts.size() == " + contracts.size());
Jamel.println("this.capacity == " + this.capacity);
Jamel.println();
throw new RuntimeException("Overcapacity");
}
final int[] newMaterials = new int[this.productionProcessLenght];
final long[] newValues = new long[this.productionProcessLenght];
int stage = this.productionProcessLenght - 1;
for (final LaborContract contract : contracts) {
while (true) {
if (stage == 0 || this.materials[stage - 1] >= this.productivity) {
contract.getWorker().work();
if (stage != 0) {
final long valueTransfered = this.values[stage - 1] * this.productivity
/ this.materials[stage - 1];
this.values[stage - 1] -= valueTransfered;
newValues[stage] += valueTransfered;
this.materials[stage - 1] -= this.productivity;
}
newMaterials[stage] += this.productivity;
newValues[stage] += contract.getWage();
break;
}
stage--;
}
stage--;
if (stage == -1) {
stage = this.productionProcessLenght - 1;
}
}
// Compilation des productions de la période avec les productions des
// périodes antérieures.
for (stage = 0; stage < this.productionProcessLenght; stage++) {
this.materials[stage] += newMaterials[stage];
this.values[stage] += newValues[stage];
}
this.dataset.put("productionValue", this.values[this.productionProcessLenght - 1]);
this.dataset.put("productionVolume", this.materials[this.productionProcessLenght - 1]);
this.finishedGoods.add(this.materials[this.productionProcessLenght - 1],
this.values[this.productionProcessLenght - 1]);
this.materials[this.productionProcessLenght - 1] = 0;
this.values[this.productionProcessLenght - 1] = 0;
}
}