package mods.eln.sixnode.electricalmath;
import mods.eln.i18n.I18N;
import mods.eln.misc.Direction;
import mods.eln.misc.LRDU;
import mods.eln.misc.Utils;
import mods.eln.node.Node;
import mods.eln.node.six.SixNode;
import mods.eln.node.six.SixNodeDescriptor;
import mods.eln.node.six.SixNodeElement;
import mods.eln.node.six.SixNodeElementInventory;
import mods.eln.sim.ElectricalLoad;
import mods.eln.sim.IProcess;
import mods.eln.sim.ThermalLoad;
import mods.eln.sim.nbt.NbtElectricalGateInput;
import mods.eln.sim.nbt.NbtElectricalGateOutput;
import mods.eln.sim.nbt.NbtElectricalGateOutputProcess;
import mods.eln.solver.Equation;
import mods.eln.solver.ISymbole;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.inventory.Container;
import net.minecraft.inventory.IInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
public class ElectricalMathElement extends SixNodeElement {
NbtElectricalGateOutput gateOutput = new NbtElectricalGateOutput("gateOutput");
NbtElectricalGateOutputProcess gateOutputProcess = new NbtElectricalGateOutputProcess("gateOutputProcess", gateOutput);
NbtElectricalGateInput[] gateInput = new NbtElectricalGateInput[]{new NbtElectricalGateInput("gateA"), new NbtElectricalGateInput("gateB"), new NbtElectricalGateInput("gateC")};
ArrayList<ISymbole> symboleList = new ArrayList<ISymbole>();
ElectricalMathElectricalProcess electricalProcess = new ElectricalMathElectricalProcess(this);
boolean firstBoot = true;
boolean sideConnectionEnable[] = new boolean[3];
String expression = "";
Equation equation;
boolean equationIsValid;
int redstoneRequired;
boolean redstoneReady = false;
SixNodeElementInventory inventory = new SixNodeElementInventory(1, 64, this);
static final byte setExpressionId = 1;
public ElectricalMathElement(SixNode sixNode, Direction side, SixNodeDescriptor descriptor) {
super(sixNode, side, descriptor);
electricalLoadList.add(gateOutput);
electricalLoadList.add(gateInput[0]);
electricalLoadList.add(gateInput[1]);
electricalLoadList.add(gateInput[2]);
electricalComponentList.add(gateOutputProcess);
electricalProcessList.add(electricalProcess);
symboleList.add(new GateInputSymbol("A", gateInput[0]));
symboleList.add(new GateInputSymbol("B", gateInput[1]));
symboleList.add(new GateInputSymbol("C", gateInput[2]));
symboleList.add(new DayTime());
}
class GateInputSymbol implements ISymbole {
private String name;
private NbtElectricalGateInput gate;
public GateInputSymbol(String name, NbtElectricalGateInput gate) {
this.name = name;
this.gate = gate;
}
@Override
public double getValue() {
return gate.getNormalized();
}
@Override
public String getName() {
return name;
}
}
class ElectricalMathElectricalProcess implements IProcess {
private ElectricalMathElement e;
ElectricalMathElectricalProcess(ElectricalMathElement e) {
this.e = e;
}
@Override
public void process(double time) {
if (e.redstoneReady)
e.gateOutputProcess.setOutputNormalizedSafe(e.equation.getValue(time));
else
e.gateOutputProcess.setOutputNormalized(0.0);
}
}
void preProcessEquation(String expression) {
this.expression = expression;
equation = new Equation(); //expression, symboleList, 100);
equation.setUpDefaultOperatorAndMapper();
equation.setIterationLimit(100);
equation.addSymbol(symboleList);
equation.preProcess(expression);
for (int idx = 0; idx < 3; idx++) {
sideConnectionEnable[idx] = equation.isSymboleUsed(symboleList.get(idx));
}
this.expression = expression;
redstoneRequired = 0;
if (equationIsValid = equation.isValid()) {
redstoneRequired = equation.getOperatorCount();
}
checkRedstone();
}
public class DayTime implements ISymbole {
@Override
public double getValue() {
return sixNode.coordonate.world().getWorldTime() / (24000.0 - 1.0);
}
@Override
public String getName() {
return "daytime";
}
}
@Override
public ElectricalLoad getElectricalLoad(LRDU lrdu) {
if (lrdu == front) return gateOutput;
if (lrdu == front.left() && sideConnectionEnable[2]) return gateInput[2];
if (lrdu == front.inverse() && sideConnectionEnable[1]) return gateInput[1];
if (lrdu == front.right() && sideConnectionEnable[0]) return gateInput[0];
return null;
}
@Override
public ThermalLoad getThermalLoad(LRDU lrdu) {
return null;
}
@Override
public int getConnectionMask(LRDU lrdu) {
if (lrdu == front) return Node.maskElectricalOutputGate;
if (lrdu == front.left() && sideConnectionEnable[2]) return Node.maskElectricalInputGate;
if (lrdu == front.inverse() && sideConnectionEnable[1]) return Node.maskElectricalInputGate;
if (lrdu == front.right() && sideConnectionEnable[0]) return Node.maskElectricalInputGate;
return 0;
}
@Override
public String multiMeterString() {
return Utils.plotVolt("Uout:", gateOutput.getU()) + Utils.plotAmpere("Iout:", gateOutput.getCurrent());
}
@Override
public Map<String, String> getWaila() {
Map<String, String> info = new HashMap<String, String>();
info.put(I18N.tr("Equation"), expression);
info.put(I18N.tr("Input voltages"),
Utils.plotVolt("\u00A7c", gateInput[0].getU()) +
Utils.plotVolt("\u00A7a", gateInput[1].getU()) +
Utils.plotVolt("\u00A79", gateInput[2].getU()));
info.put(I18N.tr("Output voltage"), Utils.plotVolt("", gateOutput.getU()));
return info;
}
@Override
public String thermoMeterString() {
return null;
}
@Override
public void initialize() {
if (firstBoot) preProcessEquation(expression);
}
@Override
protected void inventoryChanged() {
super.inventoryChanged();
checkRedstone();
}
void checkRedstone() {
int redstoneInStack = 0;
ItemStack stack = inventory.getStackInSlot(ElectricalMathContainer.restoneSlotId);
if (stack != null) redstoneInStack = stack.stackSize;
redstoneReady = redstoneRequired <= redstoneInStack;
needPublish();
}
@Override
public IInventory getInventory() {
return inventory;
}
@Override
public boolean hasGui() {
return true;
}
@Override
public Container newContainer(Direction side, EntityPlayer player) {
return new ElectricalMathContainer(sixNode, player, inventory);
}
@Override
public void writeToNBT(NBTTagCompound nbt) {
super.writeToNBT(nbt);
nbt.setString("expression", expression);
equation.writeToNBT(nbt, "equation");
}
@Override
public void readFromNBT(NBTTagCompound nbt) {
super.readFromNBT(nbt);
expression = nbt.getString("expression");
preProcessEquation(expression);
equation.readFromNBT(nbt, "equation");
firstBoot = false;
}
@Override
public void networkSerialize(DataOutputStream stream) {
super.networkSerialize(stream);
try {
stream.writeUTF(expression);
stream.writeInt(redstoneRequired);
stream.writeBoolean(equationIsValid);
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void networkUnserialize(DataInputStream stream, EntityPlayerMP player) {
super.networkUnserialize(stream, player);
try {
switch (stream.readByte()) {
case setExpressionId:
preProcessEquation(stream.readUTF());
reconnect();
break;
}
} catch (IOException e) {
e.printStackTrace();
}
}
}