package de.ph87.electro.circuit.part; import de.ph87.electro.circuit.Circuit; import de.ph87.electro.circuit.part.junction.Junction; import de.ph87.electro.circuit.part.junction.JunctionDto; import de.ph87.electro.circuit.part.parts.*; import lombok.Getter; import lombok.Setter; import lombok.ToString; import java.awt.*; import java.util.List; import java.util.*; import static de.ph87.electro.CONFIG.PART_BACKGROUND; import static de.ph87.electro.CONFIG.RASTER; import static de.ph87.electro.circuit.part.Position.ZERO; @ToString(onlyExplicitlyIncluded = true) public abstract class Part { private final Circuit circuit; @Getter @ToString.Include private final String uuid; @Getter @Setter @ToString.Include private String name; @Getter private Position position; @Getter private Orientation orientation = Orientation.R0; @Getter private final List junctions = new ArrayList<>(); protected final Render render = new Render(); protected Part(final Circuit circuit, final String name, final Position position) { this.circuit = circuit; this.uuid = UUID.randomUUID().toString(); this.name = name; setPosition(position); } protected Part(final Circuit circuit, final PartDto dto) { this.circuit = circuit; this.uuid = dto.getUuid(); this.name = dto.getName(); this.orientation = dto.getOrientation(); setPosition(new Position(dto.getPosition())); } protected Junction addJunction(final String name, final int x, final int y) { return addJunction(new Junction(this, name, new Point(x, y))); } protected Junction addJunction(final JunctionDto dto, final int x, final int y) { return addJunction(new Junction(this, dto, new Point(x, y))); } private Junction addJunction(final Junction junction) { junctions.add(junction); return junction; } public void setPosition(final Position position) { this.position = position.alignToRaster(); junctions.forEach(Junction::updatePosition); } public void rotate() { orientation = orientation.clockwise(); junctions.forEach(Junction::updatePosition); evaluate(); } public void render() { render.rect(ZERO, RASTER, RASTER, null, null, PART_BACKGROUND); _labels(); render.resetTransform(); _render(); render.resetTransform(); junctions.forEach(junction -> junction.render(render)); render.resetTransform(); } public void paint(final Graphics2D g) { g.drawImage(render.getImage(), position.absolute.x, position.absolute.y, null); } public Optional findJunctionByUuid(final String junctionUuid) { return junctions.stream().filter(junction -> junction.getUuid().equals(junctionUuid)).findFirst(); } public Optional findJunctionByPosition(final Position position) { return junctions.stream().filter(junction -> junction.intersects(position)).findFirst(); } public final void action() { _action(); evaluate(); } public void _action() { // may be overwritten } public void postCalculate() { // may be overwritten } protected void _render() { // may be overwritten } protected void _labels() { // may be overwritten } protected void evaluate() { if (circuit != null) { circuit.evaluate(); } } public List getInnerConnections() { return Collections.emptyList(); } public static Part of(final Circuit circuit, final PartDto abstractDto) { return switch (abstractDto) { case final BatteryDto dto -> new Battery(circuit, dto); case final ConnectorCornerDto dto -> new ConnectorCorner(circuit, dto); case final ConnectorEdgeDto dto -> new ConnectorEdge(circuit, dto); case final ConnectorMiddleDto dto -> new ConnectorMiddle(circuit, dto); case final LightDto dto -> new Light(circuit, dto); case final Switch1x1Dto dto -> new Switch1x1(circuit, dto); case final Switch1x2Dto dto -> new Switch1x2(circuit, dto); case final SwitchCrossDto dto -> new SwitchCross(circuit, dto); case null, default -> throw new RuntimeException(); }; } }