KinderElektro/src/main/java/de/ph87/electro/circuit/Circuit.java
2024-05-23 15:22:05 +02:00

152 lines
4.0 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.Position;
import de.ph87.electro.circuit.part.junction.Junction;
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.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;
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) {
created = dto.getCreated();
for (PartDto partDto : dto.getParts()) {
final Part part = Part.fromDto(this, partDto);
verifyFree(part.getPosition());
parts.add(part);
}
for (final WireDto wire : dto.getWires()) {
final Junction a = findJunctionByUuid(wire.getA()).orElseThrow();
final Junction b = findJunctionByUuid(wire.getB()).orElseThrow();
wires.add(new Wire(a, b));
}
evaluate();
}
public void connect(final Junction a, final Junction b) {
wires.add(new Wire(a, b));
evaluate();
}
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);
evaluate();
}
public <T extends Part> T addPart(final T part) {
if (parts.contains(part)) {
throw new RuntimeException();
}
verifyFree(part.getPosition());
parts.add(part);
part.render();
evaluate();
return part;
}
public void removePart(final Part part) {
if (parts.remove(part)) {
part.getJunctions().stream().flatMap(junction -> junction.getWires().stream()).toList().forEach(this::disconnect); // jep, first toList(), then forEach (due to concurrent modification)
} else {
throw new RuntimeException();
}
evaluate();
}
public void movePart(final Part part, final Position position) {
if (!parts.contains(part)) {
throw new RuntimeException();
}
verifyFree(position);
part.setPosition(position);
evaluate();
}
public void evaluate() {
Calculation.calculate(this);
parts.forEach(Part::render);
save();
}
public void save() {
CircuitIOService.save(this);
}
private void verifyFree(final Position position) {
if (parts.stream().anyMatch(part -> part.getPosition().equals(position))) {
throw new RuntimeException();
}
}
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 Position position) {
return streamParts().filter(p -> p.getPosition().raster.equals(position.raster)).findFirst();
}
public Optional<Junction> findJunctionByAbsolute(final Position position) {
return findPartByPosition(position).flatMap(part -> part.findJunctionByPosition(position));
}
public Optional<Junction> findJunctionByUuid(@NonNull final String junctionUuid) {
return parts.stream().map(part -> part.findJunctionByUuid(junctionUuid)).filter(Optional::isPresent).map(Optional::get).findFirst();
}
public Optional<Wire> findWireByPosition(final Position 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"));
}
}