KinderElektro/src/main/java/de/ph87/electro/circuit/Circuit.java

137 lines
3.6 KiB
Java

package de.ph87.electro.circuit;
import de.ph87.electro.circuit.calculation.Calculation;
import de.ph87.electro.circuit.part.Part;
import de.ph87.electro.circuit.part.PartDto;
import de.ph87.electro.circuit.part.node.Node;
import de.ph87.electro.circuit.wire.Wire;
import de.ph87.electro.circuit.wire.WireDto;
import lombok.Getter;
import lombok.NonNull;
import lombok.Setter;
import java.awt.*;
import java.io.File;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Stream;
import static de.ph87.electro.CONFIG.ALIGN;
public class Circuit {
@Getter
private final String created;
@Getter
private final List<Part> parts = new ArrayList<>();
private final List<Wire> wires = new ArrayList<>();
@Setter
@Getter
private File file = null;
public Circuit() {
this.created = ZonedDateTime.now().format(DateTimeFormatter.ISO_OFFSET_DATE_TIME);
}
@SuppressWarnings("unused")
public Circuit(final File file, final CircuitDto dto) {
this.created = dto.getCreated();
for (PartDto partDto : dto.getParts()) {
final Part part = Part.fromDto(partDto);
verifyFree(part.getPosition());
parts.add(part);
}
for (final WireDto wire : dto.getWires()) {
final Node a = findNodeByUuid(wire.getA()).orElseThrow();
final Node b = findNodeByUuid(wire.getB()).orElseThrow();
wires.add(new Wire(a, b));
}
}
public Wire connect(final Node a, final Node b) {
final Wire wire = new Wire(a, b);
wires.add(wire);
return wire;
}
public void disconnect(final Wire wire) {
if (!wires.contains(wire)) {
throw new RuntimeException();
}
wires.remove(wire);
wire.getA().getWires().remove(wire);
wire.getB().getWires().remove(wire);
}
public <T extends Part> T addPart(final T part) {
if (parts.contains(part)) {
throw new RuntimeException();
}
verifyFree(part.getPosition());
parts.add(part);
return part;
}
public void removePart(final Part part) {
if (parts.remove(part)) {
part.getNodes().stream().flatMap(node -> node.getWires().stream()).toList().forEach(this::disconnect); // jep, first toList(), then forEach (due to concurrent modification)
} else {
throw new RuntimeException();
}
}
public void verifyFree(final Point position) {
if (isOccupied(position)) {
throw new RuntimeException();
}
}
public boolean isOccupied(final Point position) {
final Point aligned = ALIGN(position);
return parts.stream().anyMatch(part -> part.getPosition().equals(aligned));
}
public Stream<Part> streamParts() {
return parts.stream();
}
public Stream<Wire> streamWires() {
return wires.stream();
}
public int getPartCount() {
return parts.size();
}
public Optional<Part> findPartByPosition(final Point position) {
final Point aligned = ALIGN(position);
return streamParts().filter(p -> p.getPosition().equals(aligned)).findFirst();
}
public Optional<Node> findNodeByUuid(@NonNull final String nodeUuid) {
return parts.stream().map(part -> part.findNodeByUuid(nodeUuid)).filter(Optional::isPresent).map(Optional::get).findFirst();
}
public Optional<Wire> findWireByPosition(final Point position) {
return wires.stream().filter(wire -> wire.intersects(position)).findFirst();
}
public File getPreviewFile() {
if (file == null) {
return null;
}
return new File(file.getAbsolutePath().replaceAll("\\.json$", ".png"));
}
public void evaluate() {
Calculation.calculate(this);
}
}