diff --git a/src/configuration/XmlConfigurationParser.java b/src/configuration/XmlConfigurationParser.java index 7a182d0..c93b6a8 100644 --- a/src/configuration/XmlConfigurationParser.java +++ b/src/configuration/XmlConfigurationParser.java @@ -41,7 +41,7 @@ public class XmlConfigurationParser implements ConfigurationParser { Document document = parseDocument(file); Map buildingsMetadata = parseBuildingsMetadata(document); - SimulationData simulationData = parseSimulationData(document); + SimulationData simulationData = parseSimulationData(document, buildingsMetadata); return new SimulationConfiguration(buildingsMetadata, simulationData); } @@ -149,7 +149,7 @@ public class XmlConfigurationParser implements ConfigurationParser { return new FactoryOutput(type); } - private SimulationData parseSimulationData(Document document) { + private SimulationData parseSimulationData(Document document, Map buildingMetadata) { Node dataNode = document.getElementsByTagName(TAG_SIMULATION_DATA).item(0); Collection buildings = new ArrayList<>(); @@ -157,7 +157,7 @@ public class XmlConfigurationParser implements ConfigurationParser { for (Element elem : new IterableElementList(dataNode.getChildNodes())) { switch (elem.getNodeName()) { - case TAG_BUILDING -> buildings.add(parseBuilding(elem)); + case TAG_BUILDING -> buildings.add(parseBuilding(elem, buildingMetadata)); case TAG_ROUTES -> routes = parseRoutes(elem); } } @@ -165,15 +165,17 @@ public class XmlConfigurationParser implements ConfigurationParser { return new SimulationData(buildings, routes); } - private Building parseBuilding(Element buildingElement) { + private Building parseBuilding(Element buildingElement, Map buildingMetadata) { String type = buildingElement.getAttribute(ATTRIBUTE_TYPE); int id = Integer.parseInt(buildingElement.getAttribute(ATTRIBUTE_ID)); int x = Integer.parseInt(buildingElement.getAttribute(ATTRIBUTE_X)); int y = Integer.parseInt(buildingElement.getAttribute(ATTRIBUTE_Y)); + BuildingMetadata metadata = buildingMetadata.get(type); + return type.equals(BuildingMetadata.TYPE_WAREHOUSE) ? - new Warehouse(id, type, x, y) : - new Factory(id, type, x, y); + new Warehouse(id, type, x, y, (WarehouseMetadata) metadata) : + new Factory(id, type, x, y, (FactoryMetadata) metadata); } private Collection parseRoutes(Element routesElement) { diff --git a/src/simulation/Building.java b/src/simulation/Building.java index 8634bd7..ea48aa3 100644 --- a/src/simulation/Building.java +++ b/src/simulation/Building.java @@ -1,5 +1,7 @@ package simulation; +import java.util.Optional; + public abstract class Building { protected final int id; protected final String type; @@ -15,6 +17,7 @@ public abstract class Building { } public abstract void processInput(Component input); + public abstract Optional update(); public int getId() { return id; diff --git a/src/simulation/Component.java b/src/simulation/Component.java index c358e2c..c527285 100644 --- a/src/simulation/Component.java +++ b/src/simulation/Component.java @@ -2,8 +2,6 @@ package simulation; import java.util.Objects; -// TODO WN: Check if we can use records - public class Component { private final ComponentType type; diff --git a/src/simulation/ComponentRoute.java b/src/simulation/ComponentRoute.java index 81ff2d3..f38b240 100644 --- a/src/simulation/ComponentRoute.java +++ b/src/simulation/ComponentRoute.java @@ -1,16 +1,31 @@ package simulation; public class ComponentRoute { + private final Component component; private final Building outputBuilding; + private int x; + private int y; - public ComponentRoute(Building outputBuilding) { + public ComponentRoute(Component component, Building outputBuilding, int x, int y) { + this.component = component; this.outputBuilding = outputBuilding; + this.x = x; + this.y = y; } - public void sendComponent(Component component) { + public Component getComponent() { + return component; } - private void outputComponent(Component component) { - outputBuilding.processInput(component); + public Building getOutputBuilding() { + return outputBuilding; + } + + public void setX(int x) { + this.x = x; + } + + public void setY(int y) { + this.y = y; } } diff --git a/src/simulation/Factory.java b/src/simulation/Factory.java index 1e2350a..1fc8742 100644 --- a/src/simulation/Factory.java +++ b/src/simulation/Factory.java @@ -1,15 +1,70 @@ package simulation; +import metadata.FactoryInput; +import metadata.FactoryMetadata; + +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; + public class Factory extends Building { - public Factory(int id, String type, int x, int y) { + private final FactoryMetadata metadata; + private final Map inputsCount = new HashMap<>(); + + private boolean isProductionStarted = false; + private long productionTicks = 0L; + + public Factory(int id, String type, int x, int y, FactoryMetadata metadata) { super(id, type, x, y); + this.metadata = metadata; + } + + @Override + public Optional update() { + if (!isProductionStarted) return Optional.empty(); + + productionTicks++; + + if (metadata.getProductionInterval() < productionTicks) { + return Optional.empty(); + } + + isProductionStarted = false; + Component newComponent = new Component(metadata.getOutput().getType()); + return Optional.of(newComponent); } - // TODO WN: Move logic outside model @Override public void processInput(Component input) { + int inputCount = 0; + if (inputsCount.containsKey(input.getType())) { + inputCount = inputsCount.get(input.getType()); + } + + inputsCount.put(input.getType(), inputCount); + + if (hasEnoughComponents()) { + startProduction(); + } } - private void buildComponent() { + private boolean hasEnoughComponents() { + for (FactoryInput input : metadata.getInputs()) { + if (!inputsCount.containsKey(input.getType()) || inputsCount.get(input.getType()) < input.getQuantity()) { + return false; + } + } + + return true; + } + + private void startProduction() { + for (FactoryInput input : metadata.getInputs()) { + int inputCount = inputsCount.get(input.getType()); + inputsCount.put(input.getType(), inputCount - input.getQuantity()); + } + + isProductionStarted = true; + productionTicks = 0; } } diff --git a/src/simulation/Warehouse.java b/src/simulation/Warehouse.java index c7241bf..977050c 100644 --- a/src/simulation/Warehouse.java +++ b/src/simulation/Warehouse.java @@ -9,11 +9,17 @@ import java.util.ArrayList; import java.util.Collection; public class Warehouse extends Building implements WarehouseSubject { + private final WarehouseMetadata metadata; private final Collection planes = new ArrayList<>(); private final Collection observers = new ArrayList<>(); - public Warehouse(int id, String type, int x, int y) { + public Warehouse(int id, String type, int x, int y, WarehouseMetadata metadata) { super(id, type, x, y); + this.metadata = metadata; + } + + @Override + public void update() { } @Override diff --git a/src/view/Environment.java b/src/view/Environment.java index 6759e85..223b989 100644 --- a/src/view/Environment.java +++ b/src/view/Environment.java @@ -4,15 +4,17 @@ import javax.swing.*; public class Environment extends SwingWorker { private static final int DELAY = 100; + public static final String TICK_PROPERTY_NAME = "tick"; private boolean active = true; + private long tick = 0L; @Override protected Object doInBackground() throws Exception { while (active) { Thread.sleep(DELAY); - firePropertyChange("TEST", null, "Ceci est un test"); + firePropertyChange(TICK_PROPERTY_NAME, tick, ++tick); } return null; } diff --git a/src/view/MainPanel.java b/src/view/MainPanel.java index 2f14812..8e4a4ec 100644 --- a/src/view/MainPanel.java +++ b/src/view/MainPanel.java @@ -4,30 +4,40 @@ import configuration.SimulationConfiguration; import configuration.SimulationConfigurationSingleton; import configuration.SimulationData; import metadata.BuildingMetadata; -import simulation.Building; -import simulation.BuildingState; -import simulation.Route; +import simulation.*; +import simulation.Component; import javax.imageio.ImageIO; import javax.swing.*; import java.awt.*; -import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.io.Serial; -import java.util.HashMap; -import java.util.Map; +import java.util.*; public class MainPanel extends JPanel { @Serial private static final long serialVersionUID = 1L; - private final Map icons = new HashMap<>(); + private final Map buildingIcons = new HashMap<>(); + private final Map componentsIcons = new HashMap<>(); private final Map buildingsById = new HashMap<>(); + private final Collection componentRoutes = new ArrayList<>(); private SimulationConfiguration configuration; private SimulationData simulationData; + public MainPanel() { + try { + componentsIcons.put(ComponentType.METAL, loadImage("src/ressources/metal.png")); + componentsIcons.put(ComponentType.MOTOR, loadImage("src/ressources/moteur.png")); + componentsIcons.put(ComponentType.PLANE, loadImage("src/ressources/avion.png")); + componentsIcons.put(ComponentType.WING, loadImage("src/ressources/aile.png")); + } catch (IOException e) { + throw new RuntimeException("Could not load components icons", e); + } + } + public void reloadSimulation() { configuration = SimulationConfigurationSingleton.getInstance().getConfiguration(); simulationData = configuration.getSimulationData(); @@ -35,16 +45,20 @@ public class MainPanel extends JPanel { buildingsById.clear(); simulationData.getBuildings().forEach(b -> buildingsById.put(b.getId(), b)); - icons.clear(); + buildingIcons.clear(); configuration.getMetadata().values().forEach(m -> { try { - loadImage(m); + loadBuildingImage(m); } catch (IOException e) { System.err.println("Could not load simulation icons"); } }); } + private final float componentSpeed = 1f; + private int componentX = 0; + private int componentY = 0; + @Override public void paint(Graphics g) { super.paint(g); @@ -57,32 +71,55 @@ public class MainPanel extends JPanel { simulationData.getRoutes().forEach(r -> paintRoute(r, g)); simulationData.getBuildings().forEach(b -> paintBuilding(b, g)); + + Image image = componentsIcons.get(ComponentType.METAL); + g.drawImage(image, componentX, componentY, null); + + componentX += 1 * componentSpeed; + componentY += 1 * componentSpeed; } private void paintBuilding(Building building, Graphics g) { - Image icon = icons.get(building.getType()); + building.update().ifPresent(component -> addComponentRoute(component, building.getId())); + + Image icon = buildingIcons.get(building.getType()); g.drawImage(icon, building.getX(), building.getY(), null); } + private void addComponentRoute(Component component, Building fromBuilding) { + Route route = simulationData.getRoutes().stream() + .filter(r -> r.getFrom() == fromBuilding.getId()) + .findFirst().get(); + + Building toBuilding = buildingsById.get(route.getTo()); + componentRoutes.add(new ComponentRoute(component, toBuilding, fromBuilding.getX(), fromBuilding.getY())); + } + private void paintRoute(Route route, Graphics g) { Building fromBuilding = buildingsById.get(route.getFrom()); - Image fromIcon = icons.get(fromBuilding.getType()); + Image fromIcon = buildingIcons.get(fromBuilding.getType()); Building toBuilding = buildingsById.get(route.getTo()); - Image toIcon = icons.get(toBuilding.getType()); + Image toIcon = buildingIcons.get(toBuilding.getType()); - g.drawLine( - fromBuilding.getX() + fromIcon.getWidth(null) / 2, - fromBuilding.getY() + fromIcon.getHeight(null) / 2, - toBuilding.getX() + toIcon.getWidth(null) / 2, - toBuilding.getY() + toIcon.getHeight(null) / 2 - ); + g.drawLine(fromBuilding.getX() + fromIcon.getWidth(null) / 2, fromBuilding.getY() + fromIcon.getHeight(null) / 2, toBuilding.getX() + toIcon.getWidth(null) / 2, toBuilding.getY() + toIcon.getHeight(null) / 2); } - private void loadImage(BuildingMetadata metadata) throws IOException { - String iconPath = metadata.getIconsPaths().get(BuildingState.EMPTY); - BufferedImage image = ImageIO.read(new File(iconPath)); + private void paintComponentRoute(ComponentRoute route, Graphics g) { + ComponentType componentType = route.getComponent().getType(); + Image componentIcon = componentsIcons.get(componentType); - icons.put(metadata.getType(), image); + Vector + } + + private void loadBuildingImage(BuildingMetadata metadata) throws IOException { + String iconPath = metadata.getIconsPaths().get(BuildingState.EMPTY); + Image image = loadImage(iconPath); + + buildingIcons.put(metadata.getType(), image); + } + + private Image loadImage(String path) throws IOException { + return ImageIO.read(new File(path)); } } diff --git a/src/view/MainWindow.java b/src/view/MainWindow.java index db65f62..e71f275 100644 --- a/src/view/MainWindow.java +++ b/src/view/MainWindow.java @@ -36,9 +36,8 @@ public class MainWindow extends JFrame implements PropertyChangeListener { @Override public void propertyChange(PropertyChangeEvent event) { - if (event.getPropertyName().equals("TEST")) { + if (event.getPropertyName().equals(Environment.TICK_PROPERTY_NAME)) { repaint(); -// System.out.println(event.getNewValue()); } } }