Fully working app
This commit is contained in:
parent
6f1a3b91aa
commit
d4af46450c
|
@ -1,7 +1,9 @@
|
|||
package configuration;
|
||||
|
||||
import metadata.BuildingMetadata;
|
||||
import simulation.Building;
|
||||
import simulation.Route;
|
||||
import simulation.Warehouse;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
|
@ -21,4 +23,10 @@ public class SimulationData {
|
|||
public Collection<Route> getRoutes() {
|
||||
return routes;
|
||||
}
|
||||
|
||||
public Warehouse getWarehouse() {
|
||||
return (Warehouse) buildings.stream()
|
||||
.filter(b -> b.getType().equals(BuildingMetadata.TYPE_WAREHOUSE))
|
||||
.findFirst().get();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -162,9 +162,24 @@ public class XmlConfigurationParser implements ConfigurationParser {
|
|||
}
|
||||
}
|
||||
|
||||
subscribeFactories(buildings);
|
||||
return new SimulationData(buildings, routes);
|
||||
}
|
||||
|
||||
private void subscribeFactories(Collection<Building> buildings) {
|
||||
Warehouse warehouse = (Warehouse) buildings.stream()
|
||||
.filter(b -> b.getType().equals(BuildingMetadata.TYPE_WAREHOUSE))
|
||||
.findFirst().get();
|
||||
|
||||
for (Building building : buildings) {
|
||||
if (!(building instanceof Factory)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
warehouse.attach(((Factory) building));
|
||||
}
|
||||
}
|
||||
|
||||
private Building parseBuilding(Element buildingElement, Map<String, BuildingMetadata> buildingMetadata) {
|
||||
String type = buildingElement.getAttribute(ATTRIBUTE_TYPE);
|
||||
int id = Integer.parseInt(buildingElement.getAttribute(ATTRIBUTE_ID));
|
||||
|
|
|
@ -60,7 +60,7 @@
|
|||
<usine type="usine-matiere" id="11" x="32" y="32"/>
|
||||
<usine type="usine-aile" id="21" x="320" y="32"/>
|
||||
<usine type="usine-assemblage" id="41" x="160" y="192"/>
|
||||
<usine type="entrepot" id="51" x="440" y="192"/> <!-- x=640 -->
|
||||
<usine type="entrepot" id="51" x="640" y="192"/>
|
||||
<usine type="usine-matiere" id="13" x="544" y="576"/>
|
||||
<usine type="usine-matiere" id="12" x="96" y="352"/>
|
||||
<usine type="usine-moteur" id="31" x="320" y="352"/>
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package simulation;
|
||||
|
||||
import metadata.BuildingMetadata;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public abstract class Building {
|
||||
|
@ -18,6 +20,7 @@ public abstract class Building {
|
|||
|
||||
public abstract void processInput(Component input);
|
||||
public abstract Optional<Component> update();
|
||||
public abstract BuildingMetadata getMetadata();
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
|
|
|
@ -15,6 +15,10 @@ public enum ComponentType {
|
|||
this.typeName = typeName;
|
||||
}
|
||||
|
||||
public String getTypeName() {
|
||||
return typeName;
|
||||
}
|
||||
|
||||
public static ComponentType getForTypeName(String typeName) {
|
||||
return Arrays.stream(ComponentType.values())
|
||||
.filter(t -> Objects.equals(t.typeName, typeName))
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package simulation;
|
||||
|
||||
import metadata.BuildingMetadata;
|
||||
import metadata.FactoryInput;
|
||||
import metadata.FactoryMetadata;
|
||||
|
||||
|
@ -7,11 +8,12 @@ import java.util.HashMap;
|
|||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
public class Factory extends Building {
|
||||
public class Factory extends Building implements WarehouseObserver {
|
||||
private final FactoryMetadata metadata;
|
||||
private final Map<ComponentType, Integer> inputsCount = new HashMap<>();
|
||||
|
||||
private boolean isProductionStarted;
|
||||
private boolean warehouseFull;
|
||||
private long productionTicks = 0L;
|
||||
|
||||
public Factory(int id, String type, int x, int y, FactoryMetadata metadata) {
|
||||
|
@ -27,20 +29,11 @@ public class Factory extends Building {
|
|||
|
||||
@Override
|
||||
public Optional<Component> update() {
|
||||
if (!isProductionStarted) return Optional.empty();
|
||||
if (!isProductionStarted || (productionTicks == 0 && warehouseFull)) return Optional.empty();
|
||||
|
||||
productionTicks++;
|
||||
float productionInterval = metadata.getProductionInterval();
|
||||
if (productionTicks < productionInterval) {
|
||||
|
||||
if (productionTicks / productionInterval >= (2 / 3f)) {
|
||||
state = BuildingState.FULL;
|
||||
} else if (productionTicks / productionInterval >= (1 / 3f)) {
|
||||
state = BuildingState.TWO_THIRD;
|
||||
} else {
|
||||
state = BuildingState.ONE_THIRD;
|
||||
}
|
||||
|
||||
if (productionTicks < metadata.getProductionInterval()) {
|
||||
updateState();
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
|
@ -68,6 +61,27 @@ public class Factory extends Building {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public BuildingMetadata getMetadata() {
|
||||
return metadata;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateWarehouseState(boolean full) {
|
||||
warehouseFull = full;
|
||||
}
|
||||
|
||||
private void updateState() {
|
||||
float productionRatio = productionTicks / (float) metadata.getProductionInterval();
|
||||
if (productionRatio >= (2 / 3f)) {
|
||||
state = BuildingState.FULL;
|
||||
} else if (productionRatio >= (1 / 3f)) {
|
||||
state = BuildingState.TWO_THIRD;
|
||||
} else {
|
||||
state = BuildingState.ONE_THIRD;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean hasEnoughComponents() {
|
||||
for (FactoryInput input : metadata.getInputs()) {
|
||||
if (!inputsCount.containsKey(input.getType()) || inputsCount.get(input.getType()) < input.getQuantity()) {
|
||||
|
@ -94,16 +108,12 @@ public class Factory extends Building {
|
|||
|
||||
if (!inputsCount.isEmpty()) {
|
||||
for (ComponentType type : inputsCount.keySet()) {
|
||||
builder.append(type.toString())
|
||||
.append(": ")
|
||||
.append(inputsCount.get(type));
|
||||
builder.append(type.toString()).append(": ").append(inputsCount.get(type));
|
||||
}
|
||||
}
|
||||
|
||||
if (isProductionStarted) {
|
||||
builder.append(" (interval: ")
|
||||
.append(productionTicks)
|
||||
.append(')');
|
||||
builder.append(" (interval: ").append(productionTicks).append(')');
|
||||
}
|
||||
|
||||
builder.append(']');
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
package simulation;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
public class RandomSellStrategy implements SellStrategy {
|
||||
private static final int SELL_CHANCE_PERCENT = 1;
|
||||
|
||||
private final Random random = new Random();
|
||||
|
||||
@Override
|
||||
public boolean shouldSell() {
|
||||
int gen = random.nextInt(100);
|
||||
return gen < SELL_CHANCE_PERCENT;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
package simulation;
|
||||
|
||||
public interface SellStrategy {
|
||||
boolean shouldSell();
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
package simulation;
|
||||
|
||||
public class TimedSellStrategy implements SellStrategy {
|
||||
private static final int SELL_INTERVAL = 300;
|
||||
|
||||
private long tick = 0L;
|
||||
|
||||
@Override
|
||||
public boolean shouldSell() {
|
||||
return ++tick % SELL_INTERVAL == 0;
|
||||
}
|
||||
}
|
|
@ -1,7 +1,5 @@
|
|||
package simulation;
|
||||
|
||||
import configuration.SimulationConfiguration;
|
||||
import configuration.SimulationConfigurationSingleton;
|
||||
import metadata.BuildingMetadata;
|
||||
import metadata.WarehouseMetadata;
|
||||
|
||||
|
@ -11,26 +9,62 @@ import java.util.Optional;
|
|||
|
||||
public class Warehouse extends Building implements WarehouseSubject {
|
||||
private final WarehouseMetadata metadata;
|
||||
private final int capacity;
|
||||
private final Collection<WarehouseObserver> observers = new ArrayList<>();
|
||||
|
||||
private SellStrategy sellStrategy = new TimedSellStrategy();
|
||||
private int planeCount = 0;
|
||||
|
||||
public Warehouse(int id, String type, int x, int y, WarehouseMetadata metadata) {
|
||||
super(id, type, x, y);
|
||||
|
||||
this.metadata = metadata;
|
||||
this.capacity = metadata.getInput().getCapacity();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Component> update() {
|
||||
if (planeCount > 0 && sellStrategy.shouldSell()) {
|
||||
sellPlane();
|
||||
}
|
||||
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processInput(Component input) {
|
||||
planeCount++;
|
||||
updateState();
|
||||
notifyObservers();
|
||||
}
|
||||
|
||||
private void sellComponent() {
|
||||
@Override
|
||||
public BuildingMetadata getMetadata() {
|
||||
return metadata;
|
||||
}
|
||||
|
||||
public void setSellStrategy(SellStrategy sellStrategy) {
|
||||
this.sellStrategy = sellStrategy;
|
||||
}
|
||||
|
||||
private void updateState() {
|
||||
float fullRatio = planeCount / (float) capacity;
|
||||
if (fullRatio >= 1) {
|
||||
state = BuildingState.FULL;
|
||||
} else if (fullRatio >= (2 / 3f)) {
|
||||
state = BuildingState.TWO_THIRD;
|
||||
} else if (fullRatio >= (1 / 3f)) {
|
||||
state = BuildingState.ONE_THIRD;
|
||||
} else {
|
||||
state = BuildingState.EMPTY;
|
||||
}
|
||||
}
|
||||
|
||||
private void sellPlane() {
|
||||
// Vend un avion
|
||||
planeCount--;
|
||||
updateState();
|
||||
notifyObservers();
|
||||
}
|
||||
|
||||
public void attach(WarehouseObserver observer) {
|
||||
|
@ -42,20 +76,13 @@ public class Warehouse extends Building implements WarehouseSubject {
|
|||
}
|
||||
|
||||
public void notifyObservers() {
|
||||
boolean isFull = planeCount >= getCapacity();
|
||||
observers.forEach(o -> o.update(isFull));
|
||||
}
|
||||
|
||||
private static int getCapacity() {
|
||||
SimulationConfiguration configuration = SimulationConfigurationSingleton.getInstance().getConfiguration();
|
||||
WarehouseMetadata metadata = (WarehouseMetadata) configuration.getMetadata().get(BuildingMetadata.TYPE_WAREHOUSE);
|
||||
|
||||
return metadata.getInput().getCapacity();
|
||||
boolean isFull = planeCount >= capacity;
|
||||
observers.forEach(o -> o.updateWarehouseState(isFull));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
boolean isFull = planeCount >= getCapacity();
|
||||
boolean isFull = planeCount >= capacity;
|
||||
|
||||
return String.format("[planes: %d, full: %s]", planeCount, isFull);
|
||||
}
|
||||
|
|
|
@ -6,5 +6,5 @@ public interface WarehouseObserver {
|
|||
*
|
||||
* @param full Si l'entrepot est plein ou non
|
||||
*/
|
||||
void update(boolean full);
|
||||
void updateWarehouseState(boolean full);
|
||||
}
|
||||
|
|
|
@ -3,59 +3,67 @@ package view;
|
|||
import configuration.SimulationConfiguration;
|
||||
import configuration.SimulationConfigurationSingleton;
|
||||
import configuration.SimulationData;
|
||||
import metadata.BuildingMetadata;
|
||||
import simulation.Building;
|
||||
import simulation.Component;
|
||||
import simulation.*;
|
||||
import simulation.Route;
|
||||
import view.components.BuildingIcon;
|
||||
import view.components.ComponentIcon;
|
||||
import view.components.RouteLine;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.Serial;
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class MainPanel extends JPanel {
|
||||
public class MainPanel extends JLayeredPane {
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final Map<String, Map<BuildingState, Image>> buildingIcons = new HashMap<>();
|
||||
private final Map<ComponentType, Image> componentsIcons = new HashMap<>();
|
||||
private final Map<Integer, Building> buildingsById = new HashMap<>();
|
||||
private final Collection<ComponentRoute> componentRoutes = new ArrayList<>();
|
||||
private final Collection<ComponentIcon> componentIcons = 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();
|
||||
|
||||
buildingsById.clear();
|
||||
simulationData.getBuildings().forEach(b -> buildingsById.put(b.getId(), b));
|
||||
|
||||
buildingIcons.clear();
|
||||
configuration.getMetadata().values().forEach(m -> {
|
||||
try {
|
||||
loadBuildingImages(m);
|
||||
} catch (IOException e) {
|
||||
System.err.println("Could not load simulation icons");
|
||||
}
|
||||
});
|
||||
int routesOffset = 0;
|
||||
for (Building building : simulationData.getBuildings()) {
|
||||
BuildingIcon icon = this.initializeBuilding(building);
|
||||
routesOffset = icon.getWidth() / 2;
|
||||
}
|
||||
|
||||
for (Route route : simulationData.getRoutes()) {
|
||||
initializeRoute(route, routesOffset);
|
||||
}
|
||||
}
|
||||
|
||||
int x = 0;
|
||||
private BuildingIcon initializeBuilding(Building building) {
|
||||
buildingsById.put(building.getId(), building);
|
||||
|
||||
BuildingIcon icon = new BuildingIcon(building);
|
||||
add(icon);
|
||||
setLayer(icon, 2);
|
||||
|
||||
return icon;
|
||||
}
|
||||
|
||||
private void initializeRoute(Route route, int offset) {
|
||||
Building from = getBuildingById(route.getFrom());
|
||||
Building to = getBuildingById(route.getTo());
|
||||
|
||||
RouteLine line = new RouteLine(from, to, offset);
|
||||
|
||||
add(line);
|
||||
setLayer(line, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paint(Graphics g) {
|
||||
|
@ -63,30 +71,29 @@ public class MainPanel extends JPanel {
|
|||
|
||||
if (configuration == null) return;
|
||||
|
||||
simulationData.getRoutes().forEach(r -> paintRoute(r, g));
|
||||
simulationData.getBuildings().forEach(b -> paintBuilding(b, g));
|
||||
updateBuildings();
|
||||
|
||||
Collection<ComponentRoute> removedComponentRoutes = new ArrayList<>();
|
||||
for (ComponentRoute route : componentRoutes) {
|
||||
paintComponentRoute(route, g);
|
||||
Collection<ComponentIcon> removedIcons = new ArrayList<>();
|
||||
|
||||
if (route.isTransitFinished()) {
|
||||
removedComponentRoutes.add(route);
|
||||
route.sendToOutputBuilding();
|
||||
for (ComponentIcon icon : componentIcons) {
|
||||
if (icon.isAtDestination()) {
|
||||
removedIcons.add(icon);
|
||||
}
|
||||
}
|
||||
|
||||
// Prevent concurrency problems
|
||||
componentRoutes.removeAll(removedComponentRoutes);
|
||||
removedIcons.forEach(i -> {
|
||||
componentIcons.remove(i);
|
||||
remove(i);
|
||||
|
||||
Building outputBuilding = getBuildingById(i.getDestinationId());
|
||||
outputBuilding.processInput(i.getComponent());
|
||||
});
|
||||
}
|
||||
|
||||
private void paintBuilding(Building building, Graphics g) {
|
||||
building.update().ifPresent(component -> addComponentRoute(component, building));
|
||||
|
||||
Image icon = buildingIcons.get(building.getType()).get(building.getState());
|
||||
g.drawImage(icon, building.getX(), building.getY(), null);
|
||||
|
||||
g.drawString(building.toString(), building.getX() - 20, building.getY() - 5);
|
||||
private void updateBuildings() {
|
||||
simulationData.getBuildings().forEach(b -> {
|
||||
b.update().ifPresent(c -> addComponentRoute(c, b));
|
||||
});
|
||||
}
|
||||
|
||||
private void addComponentRoute(Component component, Building fromBuilding) {
|
||||
|
@ -95,48 +102,17 @@ public class MainPanel extends JPanel {
|
|||
.findFirst().get();
|
||||
|
||||
Building toBuilding = buildingsById.get(route.getTo());
|
||||
componentRoutes.add(new ComponentRoute(component, toBuilding, fromBuilding.getX(), fromBuilding.getY()));
|
||||
Point fromPosition = new Point(fromBuilding.getX(), fromBuilding.getY());
|
||||
Point toPosition = new Point(toBuilding.getX(), toBuilding.getY());
|
||||
|
||||
ComponentIcon icon = new ComponentIcon(component, route.getTo(), fromPosition, toPosition);
|
||||
componentIcons.add(icon);
|
||||
|
||||
add(icon);
|
||||
setLayer(icon, 1);
|
||||
}
|
||||
|
||||
private void paintRoute(Route route, Graphics g) {
|
||||
Building fromBuilding = buildingsById.get(route.getFrom());
|
||||
Image fromIcon = buildingIcons.get(fromBuilding.getType()).get(fromBuilding.getState());
|
||||
|
||||
Building toBuilding = buildingsById.get(route.getTo());
|
||||
Image toIcon = buildingIcons.get(toBuilding.getType()).get(fromBuilding.getState());
|
||||
|
||||
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 paintComponentRoute(ComponentRoute route, Graphics g) {
|
||||
ComponentType componentType = route.getComponent().getType();
|
||||
Image componentIcon = componentsIcons.get(componentType);
|
||||
|
||||
route.updatePosition();
|
||||
|
||||
g.drawImage(componentIcon, route.getX(), route.getY(), null);
|
||||
}
|
||||
|
||||
private void loadBuildingImages(BuildingMetadata metadata) throws IOException {
|
||||
Map<BuildingState, Image> statesIcons = new HashMap<>();
|
||||
for (BuildingState state : BuildingState.values()) {
|
||||
statesIcons.put(state, loadBuildingImage(metadata, state));
|
||||
}
|
||||
|
||||
buildingIcons.put(metadata.getType(), statesIcons);
|
||||
}
|
||||
|
||||
private Image loadBuildingImage(BuildingMetadata metadata, BuildingState state) throws IOException {
|
||||
String iconPath = metadata.getIconsPaths().get(state);
|
||||
return loadImage(iconPath);
|
||||
}
|
||||
|
||||
private Image loadImage(String path) throws IOException {
|
||||
return ImageIO.read(new File(path));
|
||||
private Building getBuildingById(int id) {
|
||||
return buildingsById.get(id);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ public class MainWindow extends JFrame implements PropertyChangeListener {
|
|||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final String WINDOW_TITLE = "Laboratoire 1 : LOG121 - Simulation";
|
||||
private static final Dimension DIMENSION = new Dimension(700, 700);
|
||||
public static final Dimension DIMENSION = new Dimension(700, 700);
|
||||
|
||||
public MainWindow() {
|
||||
MainPanel mainPanel = new MainPanel();
|
||||
|
|
|
@ -1,5 +1,11 @@
|
|||
package view;
|
||||
|
||||
import configuration.SimulationConfigurationSingleton;
|
||||
import simulation.RandomSellStrategy;
|
||||
import simulation.SellStrategy;
|
||||
import simulation.TimedSellStrategy;
|
||||
import simulation.Warehouse;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
|
@ -11,8 +17,8 @@ public class StrategyPanel extends JPanel {
|
|||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public StrategyPanel() {
|
||||
JRadioButton strategy1 = new JRadioButton("Stratégie 1");
|
||||
JRadioButton strategy2 = new JRadioButton("Stratégie 2");
|
||||
JRadioButton strategy1 = new JRadioButton("Interval");
|
||||
JRadioButton strategy2 = new JRadioButton("Aléatoire");
|
||||
|
||||
ButtonGroup buttonGroup = new ButtonGroup();
|
||||
buttonGroup.add(strategy1);
|
||||
|
@ -20,8 +26,9 @@ public class StrategyPanel extends JPanel {
|
|||
|
||||
JButton confirmButton = new JButton("Confirmer");
|
||||
confirmButton.addActionListener((ActionEvent e) -> {
|
||||
// TODO - Appeler la bonne stratégie
|
||||
System.out.println(getSelectedButtonText(buttonGroup));
|
||||
String selectedStrategyName = getSelectedButtonText(buttonGroup);
|
||||
onStrategyChange(selectedStrategyName);
|
||||
|
||||
// Fermer la fenêtre du component
|
||||
SwingUtilities.getWindowAncestor((Component) e.getSource()).dispose();
|
||||
});
|
||||
|
@ -54,4 +61,13 @@ public class StrategyPanel extends JPanel {
|
|||
|
||||
return null;
|
||||
}
|
||||
|
||||
private void onStrategyChange(String strategyName) {
|
||||
SellStrategy strategy = strategyName.equalsIgnoreCase("Interval") ?
|
||||
new TimedSellStrategy() :
|
||||
new RandomSellStrategy();
|
||||
|
||||
Warehouse warehouse = SimulationConfigurationSingleton.getInstance().getConfiguration().getSimulationData().getWarehouse();
|
||||
warehouse.setSellStrategy(strategy);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,7 +57,6 @@ public class WindowMenu extends JMenuBar {
|
|||
|
||||
mainPanel.reloadSimulation();
|
||||
} catch (ConfigurationParsingException ex) {
|
||||
// TODO WN: Handle exception
|
||||
throw new RuntimeException("Failed to parse config file", ex);
|
||||
}
|
||||
}
|
||||
|
@ -82,7 +81,6 @@ public class WindowMenu extends JMenuBar {
|
|||
|
||||
chooseMenu.addActionListener((ActionEvent e) -> {
|
||||
// Ouvrir la fenêtre de sélection
|
||||
// TODO - Récupérer la bonne stratégie de vente
|
||||
new StrategyWindow();
|
||||
});
|
||||
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
package view.components;
|
||||
|
||||
import metadata.BuildingMetadata;
|
||||
import simulation.Building;
|
||||
import simulation.BuildingState;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class BuildingIcon extends JComponent {
|
||||
private static final Map<String, Map<BuildingState, Image>> loadedImages = new HashMap<>();
|
||||
|
||||
private final Building building;
|
||||
private final Map<BuildingState, Image> images;
|
||||
|
||||
public BuildingIcon(Building building) {
|
||||
this.building = building;
|
||||
this.images = getImages(building.getMetadata());
|
||||
|
||||
setBounds();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintComponent(Graphics g) {
|
||||
Image image = getCurrentStateImage();
|
||||
|
||||
g.drawImage(image, 0, 0, null);
|
||||
}
|
||||
|
||||
public Image getCurrentStateImage() {
|
||||
return images.get(building.getState());
|
||||
}
|
||||
|
||||
private void setBounds() {
|
||||
// Présume que toutes les icônes ont les mêmes dimensions
|
||||
Image image = images.get(BuildingState.EMPTY);
|
||||
|
||||
int x = building.getX();
|
||||
int y = building.getY();
|
||||
int width = image.getWidth(null);
|
||||
int height = image.getHeight(null);
|
||||
|
||||
setBounds(x, y, width, height);
|
||||
}
|
||||
|
||||
private static Map<BuildingState, Image> getImages(BuildingMetadata metadata) {
|
||||
if (loadedImages.containsKey(metadata.getType())) {
|
||||
return loadedImages.get(metadata.getType());
|
||||
}
|
||||
|
||||
return loadImages(metadata);
|
||||
}
|
||||
|
||||
private static Map<BuildingState, Image> loadImages(BuildingMetadata metadata) {
|
||||
Map<BuildingState, Image> images = new HashMap<>();
|
||||
|
||||
for (BuildingState state : BuildingState.values()) {
|
||||
String path = metadata.getIconsPaths().get(state);
|
||||
Image image = loadImage(path);
|
||||
|
||||
images.put(state, image);
|
||||
}
|
||||
|
||||
loadedImages.put(metadata.getType(), images);
|
||||
return images;
|
||||
}
|
||||
|
||||
private static Image loadImage(String path) {
|
||||
try {
|
||||
File file = new File(path);
|
||||
return ImageIO.read(file);
|
||||
} catch (IOException ex) {
|
||||
throw new RuntimeException("Could not load building icon", ex);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,91 @@
|
|||
package view.components;
|
||||
|
||||
import simulation.ComponentType;
|
||||
import simulation.Component;
|
||||
import view.MainWindow;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class ComponentIcon extends JComponent {
|
||||
private static final Map<ComponentType, Image> loadedImages = new HashMap<>();
|
||||
private static final int SPEED = 2;
|
||||
|
||||
private final Component component;
|
||||
private final int destinationId;
|
||||
private final Point position;
|
||||
private final Point destination;
|
||||
private final Point direction;
|
||||
private final Image image;
|
||||
|
||||
public ComponentIcon(Component component, int destinationId, Point source, Point destination) {
|
||||
this.component = component;
|
||||
this.destinationId = destinationId;
|
||||
this.position = source;
|
||||
this.destination = destination;
|
||||
|
||||
this.direction = getDirection();
|
||||
this.image = getImage(component.getType());
|
||||
|
||||
setBounds(0, 0, MainWindow.DIMENSION.width, MainWindow.DIMENSION.height);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paintComponent(Graphics g) {
|
||||
position.translate(direction.x, direction.y);
|
||||
|
||||
g.translate(position.x, position.y);
|
||||
g.drawImage(image, 0, 0, null);
|
||||
}
|
||||
|
||||
public boolean isAtDestination() {
|
||||
return position.equals(destination);
|
||||
}
|
||||
|
||||
public Component getComponent() {
|
||||
return component;
|
||||
}
|
||||
|
||||
public int getDestinationId() {
|
||||
return destinationId;
|
||||
}
|
||||
|
||||
private Point getDirection() {
|
||||
return new Point(
|
||||
normalizedDirection(position.x, destination.x),
|
||||
normalizedDirection(position.y, destination.y)
|
||||
);
|
||||
}
|
||||
|
||||
private static int normalizedDirection(int from, int to) {
|
||||
return Integer.compare(to, from) * SPEED;
|
||||
}
|
||||
|
||||
private static Image getImage(ComponentType type) {
|
||||
if (loadedImages.containsKey(type)) {
|
||||
return loadedImages.get(type);
|
||||
}
|
||||
|
||||
return loadImage(type);
|
||||
}
|
||||
|
||||
private static Image loadImage(ComponentType type) {
|
||||
try {
|
||||
String path = String.format("src/ressources/%s.png", type.getTypeName());
|
||||
File file = new File(path);
|
||||
Image image = ImageIO.read(file);
|
||||
|
||||
// Garde une référence à l'image chargée pour pouvoir la réutiliser la prochaine fois
|
||||
loadedImages.put(type, image);
|
||||
|
||||
return image;
|
||||
} catch (IOException ex) {
|
||||
throw new RuntimeException("Could not load component icon", ex);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
package view.components;
|
||||
|
||||
import simulation.Building;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
|
||||
public class RouteLine extends JComponent {
|
||||
private final Point from;
|
||||
private final Point to;
|
||||
|
||||
public RouteLine(Building fromBuilding, Building toBuilding, int offset) {
|
||||
from = new Point(fromBuilding.getX(), fromBuilding.getY());
|
||||
to = new Point(toBuilding.getX(), toBuilding.getY());
|
||||
|
||||
setBounds(from, to, offset);
|
||||
|
||||
int offsetFromOriginX = Math.min(from.x, to.x);
|
||||
int offsetFromOriginY = Math.min(from.y, to.y);
|
||||
|
||||
from.translate(-offsetFromOriginX, -offsetFromOriginY);
|
||||
to.translate(-offsetFromOriginX, -offsetFromOriginY);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintComponent(Graphics g) {
|
||||
g.drawLine(from.x, from.y, to.x, to.y);
|
||||
}
|
||||
|
||||
private void setBounds(Point from, Point to, int offset) {
|
||||
int x = Math.min(from.x, to.x);
|
||||
int y = Math.min(from.y, to.y);
|
||||
int width = Math.abs(to.x - from.x);
|
||||
int height = Math.abs(to.y - from.y);
|
||||
|
||||
// Si une des dimensions est zéro, la ligne n'apparaîtra pas.
|
||||
if (width == 0) {
|
||||
width = 1;
|
||||
}
|
||||
|
||||
if (height == 0) {
|
||||
height = 1;
|
||||
}
|
||||
|
||||
setBounds(x + offset, y + offset, width, height);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue