Start dynamic network

This commit is contained in:
william 2022-06-12 20:28:04 -04:00
parent be21c33755
commit 9445638440
9 changed files with 158 additions and 41 deletions

View File

@ -41,7 +41,7 @@ public class XmlConfigurationParser implements ConfigurationParser {
Document document = parseDocument(file); Document document = parseDocument(file);
Map<String, BuildingMetadata> buildingsMetadata = parseBuildingsMetadata(document); Map<String, BuildingMetadata> buildingsMetadata = parseBuildingsMetadata(document);
SimulationData simulationData = parseSimulationData(document); SimulationData simulationData = parseSimulationData(document, buildingsMetadata);
return new SimulationConfiguration(buildingsMetadata, simulationData); return new SimulationConfiguration(buildingsMetadata, simulationData);
} }
@ -149,7 +149,7 @@ public class XmlConfigurationParser implements ConfigurationParser {
return new FactoryOutput(type); return new FactoryOutput(type);
} }
private SimulationData parseSimulationData(Document document) { private SimulationData parseSimulationData(Document document, Map<String, BuildingMetadata> buildingMetadata) {
Node dataNode = document.getElementsByTagName(TAG_SIMULATION_DATA).item(0); Node dataNode = document.getElementsByTagName(TAG_SIMULATION_DATA).item(0);
Collection<Building> buildings = new ArrayList<>(); Collection<Building> buildings = new ArrayList<>();
@ -157,7 +157,7 @@ public class XmlConfigurationParser implements ConfigurationParser {
for (Element elem : new IterableElementList(dataNode.getChildNodes())) { for (Element elem : new IterableElementList(dataNode.getChildNodes())) {
switch (elem.getNodeName()) { switch (elem.getNodeName()) {
case TAG_BUILDING -> buildings.add(parseBuilding(elem)); case TAG_BUILDING -> buildings.add(parseBuilding(elem, buildingMetadata));
case TAG_ROUTES -> routes = parseRoutes(elem); case TAG_ROUTES -> routes = parseRoutes(elem);
} }
} }
@ -165,15 +165,17 @@ public class XmlConfigurationParser implements ConfigurationParser {
return new SimulationData(buildings, routes); return new SimulationData(buildings, routes);
} }
private Building parseBuilding(Element buildingElement) { private Building parseBuilding(Element buildingElement, Map<String, BuildingMetadata> buildingMetadata) {
String type = buildingElement.getAttribute(ATTRIBUTE_TYPE); String type = buildingElement.getAttribute(ATTRIBUTE_TYPE);
int id = Integer.parseInt(buildingElement.getAttribute(ATTRIBUTE_ID)); int id = Integer.parseInt(buildingElement.getAttribute(ATTRIBUTE_ID));
int x = Integer.parseInt(buildingElement.getAttribute(ATTRIBUTE_X)); int x = Integer.parseInt(buildingElement.getAttribute(ATTRIBUTE_X));
int y = Integer.parseInt(buildingElement.getAttribute(ATTRIBUTE_Y)); int y = Integer.parseInt(buildingElement.getAttribute(ATTRIBUTE_Y));
BuildingMetadata metadata = buildingMetadata.get(type);
return type.equals(BuildingMetadata.TYPE_WAREHOUSE) ? return type.equals(BuildingMetadata.TYPE_WAREHOUSE) ?
new Warehouse(id, type, x, y) : new Warehouse(id, type, x, y, (WarehouseMetadata) metadata) :
new Factory(id, type, x, y); new Factory(id, type, x, y, (FactoryMetadata) metadata);
} }
private Collection<Route> parseRoutes(Element routesElement) { private Collection<Route> parseRoutes(Element routesElement) {

View File

@ -1,5 +1,7 @@
package simulation; package simulation;
import java.util.Optional;
public abstract class Building { public abstract class Building {
protected final int id; protected final int id;
protected final String type; protected final String type;
@ -15,6 +17,7 @@ public abstract class Building {
} }
public abstract void processInput(Component input); public abstract void processInput(Component input);
public abstract Optional<Component> update();
public int getId() { public int getId() {
return id; return id;

View File

@ -2,8 +2,6 @@ package simulation;
import java.util.Objects; import java.util.Objects;
// TODO WN: Check if we can use records
public class Component { public class Component {
private final ComponentType type; private final ComponentType type;

View File

@ -1,16 +1,31 @@
package simulation; package simulation;
public class ComponentRoute { public class ComponentRoute {
private final Component component;
private final Building outputBuilding; 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.outputBuilding = outputBuilding;
this.x = x;
this.y = y;
} }
public void sendComponent(Component component) { public Component getComponent() {
return component;
} }
private void outputComponent(Component component) { public Building getOutputBuilding() {
outputBuilding.processInput(component); return outputBuilding;
}
public void setX(int x) {
this.x = x;
}
public void setY(int y) {
this.y = y;
} }
} }

View File

@ -1,15 +1,70 @@
package simulation; 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 class Factory extends Building {
public Factory(int id, String type, int x, int y) { private final FactoryMetadata metadata;
private final Map<ComponentType, Integer> 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); super(id, type, x, y);
this.metadata = metadata;
}
@Override
public Optional<Component> 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 @Override
public void processInput(Component input) { 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;
} }
} }

View File

@ -9,11 +9,17 @@ import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
public class Warehouse extends Building implements WarehouseSubject { public class Warehouse extends Building implements WarehouseSubject {
private final WarehouseMetadata metadata;
private final Collection<Component> planes = new ArrayList<>(); private final Collection<Component> planes = new ArrayList<>();
private final Collection<WarehouseObserver> observers = new ArrayList<>(); private final Collection<WarehouseObserver> 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); super(id, type, x, y);
this.metadata = metadata;
}
@Override
public void update() {
} }
@Override @Override

View File

@ -4,15 +4,17 @@ import javax.swing.*;
public class Environment extends SwingWorker<Object, String> { public class Environment extends SwingWorker<Object, String> {
private static final int DELAY = 100; private static final int DELAY = 100;
public static final String TICK_PROPERTY_NAME = "tick";
private boolean active = true; private boolean active = true;
private long tick = 0L;
@Override @Override
protected Object doInBackground() throws Exception { protected Object doInBackground() throws Exception {
while (active) { while (active) {
Thread.sleep(DELAY); Thread.sleep(DELAY);
firePropertyChange("TEST", null, "Ceci est un test"); firePropertyChange(TICK_PROPERTY_NAME, tick, ++tick);
} }
return null; return null;
} }

View File

@ -4,30 +4,40 @@ import configuration.SimulationConfiguration;
import configuration.SimulationConfigurationSingleton; import configuration.SimulationConfigurationSingleton;
import configuration.SimulationData; import configuration.SimulationData;
import metadata.BuildingMetadata; import metadata.BuildingMetadata;
import simulation.Building; import simulation.*;
import simulation.BuildingState; import simulation.Component;
import simulation.Route;
import javax.imageio.ImageIO; import javax.imageio.ImageIO;
import javax.swing.*; import javax.swing.*;
import java.awt.*; import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.Serial; import java.io.Serial;
import java.util.HashMap; import java.util.*;
import java.util.Map;
public class MainPanel extends JPanel { public class MainPanel extends JPanel {
@Serial @Serial
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
private final Map<String, Image> icons = new HashMap<>(); private final Map<String, Image> buildingIcons = new HashMap<>();
private final Map<ComponentType, Image> componentsIcons = new HashMap<>();
private final Map<Integer, Building> buildingsById = new HashMap<>(); private final Map<Integer, Building> buildingsById = new HashMap<>();
private final Collection<ComponentRoute> componentRoutes = new ArrayList<>();
private SimulationConfiguration configuration; private SimulationConfiguration configuration;
private SimulationData simulationData; 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() { public void reloadSimulation() {
configuration = SimulationConfigurationSingleton.getInstance().getConfiguration(); configuration = SimulationConfigurationSingleton.getInstance().getConfiguration();
simulationData = configuration.getSimulationData(); simulationData = configuration.getSimulationData();
@ -35,16 +45,20 @@ public class MainPanel extends JPanel {
buildingsById.clear(); buildingsById.clear();
simulationData.getBuildings().forEach(b -> buildingsById.put(b.getId(), b)); simulationData.getBuildings().forEach(b -> buildingsById.put(b.getId(), b));
icons.clear(); buildingIcons.clear();
configuration.getMetadata().values().forEach(m -> { configuration.getMetadata().values().forEach(m -> {
try { try {
loadImage(m); loadBuildingImage(m);
} catch (IOException e) { } catch (IOException e) {
System.err.println("Could not load simulation icons"); System.err.println("Could not load simulation icons");
} }
}); });
} }
private final float componentSpeed = 1f;
private int componentX = 0;
private int componentY = 0;
@Override @Override
public void paint(Graphics g) { public void paint(Graphics g) {
super.paint(g); super.paint(g);
@ -57,32 +71,55 @@ public class MainPanel extends JPanel {
simulationData.getRoutes().forEach(r -> paintRoute(r, g)); simulationData.getRoutes().forEach(r -> paintRoute(r, g));
simulationData.getBuildings().forEach(b -> paintBuilding(b, 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) { 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); 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) { private void paintRoute(Route route, Graphics g) {
Building fromBuilding = buildingsById.get(route.getFrom()); Building fromBuilding = buildingsById.get(route.getFrom());
Image fromIcon = icons.get(fromBuilding.getType()); Image fromIcon = buildingIcons.get(fromBuilding.getType());
Building toBuilding = buildingsById.get(route.getTo()); Building toBuilding = buildingsById.get(route.getTo());
Image toIcon = icons.get(toBuilding.getType()); Image toIcon = buildingIcons.get(toBuilding.getType());
g.drawLine( 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);
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 { private void paintComponentRoute(ComponentRoute route, Graphics g) {
String iconPath = metadata.getIconsPaths().get(BuildingState.EMPTY); ComponentType componentType = route.getComponent().getType();
BufferedImage image = ImageIO.read(new File(iconPath)); 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));
} }
} }

View File

@ -36,9 +36,8 @@ public class MainWindow extends JFrame implements PropertyChangeListener {
@Override @Override
public void propertyChange(PropertyChangeEvent event) { public void propertyChange(PropertyChangeEvent event) {
if (event.getPropertyName().equals("TEST")) { if (event.getPropertyName().equals(Environment.TICK_PROPERTY_NAME)) {
repaint(); repaint();
// System.out.println(event.getNewValue());
} }
} }
} }