diff --git a/res/stages/main-stage.fxml b/res/stages/main-stage.fxml index 3032ca0a558254be1d26f016e731e4e711779725..21c1941b9e1627e260b3f2c5f765e0bc59535401 100644 --- a/res/stages/main-stage.fxml +++ b/res/stages/main-stage.fxml @@ -56,7 +56,7 @@ <children> <Button fx:id="loadData" mnemonicParsing="false" onAction="#openLoadData" prefHeight="27.0" prefWidth="185.0" text="Charger un jeu de données" /> <Button fx:id="addData" mnemonicParsing="false" onAction="#openAddData" prefHeight="26.0" prefWidth="141.0" text="Ajouter une donnée" /> - <Button fx:id="classifyData" disable="true" mnemonicParsing="false" prefHeight="26.0" prefWidth="157.0" text="Classifier une donnée" /> + <Button fx:id="classifyData" disable="true" mnemonicParsing="false" onAction="#classifyDatas" prefHeight="26.0" prefWidth="157.0" text="Classifier les données" /> </children> </HBox> </children> diff --git a/src/main/java/fr/univlille/sae/classification/controller/AddDataController.java b/src/main/java/fr/univlille/sae/classification/controller/AddDataController.java index 6bfce0f35edd54aefd17399072aa49f0bf7ba861..370a3a2fb7effe974b6f2500759a3b74980e7fb9 100644 --- a/src/main/java/fr/univlille/sae/classification/controller/AddDataController.java +++ b/src/main/java/fr/univlille/sae/classification/controller/AddDataController.java @@ -4,13 +4,11 @@ import fr.univlille.sae.classification.model.ClassificationModel; import fr.univlille.sae.classification.model.Iris; import fr.univlille.sae.classification.view.MainStageView; import javafx.fxml.FXML; -import javafx.scene.control.Button; -import javafx.scene.control.Spinner; -import javafx.scene.control.SpinnerValueFactory; -import javafx.scene.control.TextFormatter; +import javafx.scene.control.*; import javafx.stage.Stage; import java.io.IOException; +import java.text.ParseException; import java.util.function.UnaryOperator; public class AddDataController { @@ -56,8 +54,10 @@ public class AddDataController { public void validate() throws IOException { System.out.println("validé"); + mainStageView.getController().getClassifyData().setDisable(false); + + ClassificationModel.getClassificationModel().ajouterDonnee(sepalLengthSpinner.getValue(), sepalWidthSpinner.getValue(), petalLengthSpinner.getValue(), petalWidthSpinner.getValue()); - mainStageView.update(mainStageView.getModel(),new Iris(sepalWidthSpinner.getValue(),sepalLengthSpinner.getValue(),petalWidthSpinner.getValue(),petalLengthSpinner.getValue())); stage.close(); } diff --git a/src/main/java/fr/univlille/sae/classification/controller/AxesSettingsController.java b/src/main/java/fr/univlille/sae/classification/controller/AxesSettingsController.java index 16cae7a159098b17cb3abc58e7f1c52e33d2dc7d..8c890f287f75bcf97175c66402b68f004278a50e 100644 --- a/src/main/java/fr/univlille/sae/classification/controller/AxesSettingsController.java +++ b/src/main/java/fr/univlille/sae/classification/controller/AxesSettingsController.java @@ -1,5 +1,6 @@ package fr.univlille.sae.classification.controller; +import fr.univlille.sae.classification.model.ClassificationModel; import fr.univlille.sae.classification.view.MainStageView; import javafx.fxml.FXML; import javafx.scene.control.Button; @@ -41,7 +42,10 @@ public class AxesSettingsController{ public void validate(){ mainStageView.setActualX(selectAbs.getValue().toString()); mainStageView.setActualY(selectOrd.getValue().toString()); - mainStageView.update(mainStageView.getModel()); + mainStageView.getController().getScatterChart().getXAxis().setLabel(mainStageView.getActualX()); + mainStageView.getController().getScatterChart().getYAxis().setLabel(mainStageView.getActualY()); + + mainStageView.update(ClassificationModel.getClassificationModel()); stage.close(); } } diff --git a/src/main/java/fr/univlille/sae/classification/controller/LoadDataController.java b/src/main/java/fr/univlille/sae/classification/controller/LoadDataController.java index cf27808e0137d14171c71ffaa2153cc07ff6cd8c..902fb931d0938d3ec76ea2ca6fb11bb5cb92e7fd 100644 --- a/src/main/java/fr/univlille/sae/classification/controller/LoadDataController.java +++ b/src/main/java/fr/univlille/sae/classification/controller/LoadDataController.java @@ -2,6 +2,7 @@ package fr.univlille.sae.classification.controller; import fr.univlille.sae.classification.model.ClassificationModel; import javafx.fxml.FXML; +import javafx.scene.control.Alert; import javafx.scene.control.Button; import javafx.scene.control.Label; import javafx.scene.control.TextField; @@ -29,10 +30,6 @@ public class LoadDataController { File file; - public void loadData() { - System.out.println("Loading data"); - stage.close(); - } public void openFileChooser() { @@ -49,7 +46,14 @@ public class LoadDataController { public void validate() throws IOException { if (file == null) { - stage.close(); + Alert alert = new Alert(Alert.AlertType.ERROR); + alert.setTitle("Erreur de chargement du fichier"); + alert.setHeaderText(null); + alert.initOwner(stage); + alert.setContentText("Le chargement du fichier à echoué, veuillez reessayer !"); + alert.showAndWait(); + openFileChooser(); + return; //throw exception } ClassificationModel.getClassificationModel().loadData(file); diff --git a/src/main/java/fr/univlille/sae/classification/controller/MainStageController.java b/src/main/java/fr/univlille/sae/classification/controller/MainStageController.java index 21408450a73762a7f38a082592a4389dcae1da32..bf9f71772b2d4d293772505e2f4e0b38e2b9f693 100644 --- a/src/main/java/fr/univlille/sae/classification/controller/MainStageController.java +++ b/src/main/java/fr/univlille/sae/classification/controller/MainStageController.java @@ -81,6 +81,13 @@ public class MainStageController { } + + public void classifyDatas() { + ClassificationModel.getClassificationModel().classifierDonnees(); + classifyData.setDisable(true); + } + + public ScatterChart getScatterChart() { return this.scatterChart; } @@ -88,4 +95,8 @@ public class MainStageController { public void setAxesSelected(String texte) { this.AxesSelected.setText(texte); } + + public Button getClassifyData() { + return this.classifyData; + } } diff --git a/src/main/java/fr/univlille/sae/classification/model/ClassificationModel.java b/src/main/java/fr/univlille/sae/classification/model/ClassificationModel.java index b581562f7ead46a3650364f1d033b89e6cf4d98a..8e5f9f110d98f6a657aa882db786ec2ad320cfac 100644 --- a/src/main/java/fr/univlille/sae/classification/model/ClassificationModel.java +++ b/src/main/java/fr/univlille/sae/classification/model/ClassificationModel.java @@ -9,6 +9,8 @@ import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; import java.util.*; +import java.util.concurrent.ConcurrentSkipListSet; +import java.util.concurrent.CopyOnWriteArrayList; public class ClassificationModel extends Observable { @@ -39,7 +41,7 @@ public class ClassificationModel extends Observable { private ClassificationModel(DataType type) { this.datas = new ArrayList<>(); - this.dataToClass = new ArrayList<>(); + this.dataToClass = new CopyOnWriteArrayList<>(); this.type = type; } @@ -75,16 +77,22 @@ public class ClassificationModel extends Observable { notifyObservers(); } + + public void classifierDonnees() { + dataToClass.forEach(this::classifierDonnee); + } + /** * TODO * @param data */ - public void classifierDonnee(LoadableData data) { + private void classifierDonnee(LoadableData data) { List<String> classes = new ArrayList<>(data.getClassificationTypes()); Random rdm = new Random(); data.setClassification(classes.get(rdm.nextInt(classes.size()))); notifyObservers(data); + dataToClass.remove(data); } diff --git a/src/main/java/fr/univlille/sae/classification/model/Iris.java b/src/main/java/fr/univlille/sae/classification/model/Iris.java index 5f6d3a77d66e42c1553aaf749212d29fbe88eff9..94e39725ac51f4eb727c22827f5da24c2b79d7a0 100644 --- a/src/main/java/fr/univlille/sae/classification/model/Iris.java +++ b/src/main/java/fr/univlille/sae/classification/model/Iris.java @@ -7,26 +7,37 @@ import java.util.Random; public class Iris extends LoadableData{ - @CsvBindByName(column = "sepal.width") - private double sepalWidth; + @CsvBindByName(column = "sepal.length") private double sepalLength; - @CsvBindByName(column = "petal.width") - private double petalWidth; + @CsvBindByName(column = "sepal.width") + private double sepalWidth; @CsvBindByName(column = "petal.length") private double petalLength; + @CsvBindByName(column = "petal.width") + private double petalWidth; @CsvBindByName(column = "variety") private String variety; - public Iris(double sepalWidth, double sepalLength, double petalWidth, double petalLength) { - this(sepalWidth, sepalLength, petalWidth, petalLength, "undefined"); + public Iris(double sepalLength, double sepalWidth, double petalLength, double petalWidth) { + this(sepalLength, sepalWidth, petalLength, petalWidth, "undefined"); } public Iris() { // } - public Iris(double sepalWidth, double sepalLength, double petalWidth, double petalLength, String variety) { + @Override + public String getClassification() { + return variety; + } + + @Override + public void setClassification(String classification) { + this.variety = classification; + } + + public Iris(double sepalLength, double sepalWidth, double petalLength, double petalWidth, String variety) { super(); this.sepalWidth = sepalWidth; this.sepalLength = sepalLength; @@ -51,9 +62,6 @@ public class Iris extends LoadableData{ return petalLength; } - public String getVariety() { - return variety; - } public double getDataType(String axes){ switch (axes){ @@ -85,10 +93,10 @@ public class Iris extends LoadableData{ public String[] getAttributesName() { String[] names = new String[]{ - "sepalWidth", "sepalLength", - "petalWidth", - "petalLength" + "sepalWidth", + "petalLength", + "petalWidth" }; return names; } @@ -96,10 +104,10 @@ public class Iris extends LoadableData{ @Override public String toString() { return "Iris{" + - "sepalWidth=" + sepalWidth + - ", sepalLength=" + sepalLength + - ", petalWidth=" + petalWidth + + "sepalLength=" + sepalLength + + ", sepalWidth=" + sepalWidth + ", petalLength=" + petalLength + + ", petalWidth=" + petalWidth + '}'; } } diff --git a/src/main/java/fr/univlille/sae/classification/model/LoadableData.java b/src/main/java/fr/univlille/sae/classification/model/LoadableData.java index fba0fb716aefea3f9a0fb81e584f41671130891c..033890f3c275ee90712b4680729918fb665032ff 100644 --- a/src/main/java/fr/univlille/sae/classification/model/LoadableData.java +++ b/src/main/java/fr/univlille/sae/classification/model/LoadableData.java @@ -6,7 +6,8 @@ public abstract class LoadableData { private static Set<String> classificationTypes; - private String classification; + + protected LoadableData() { @@ -16,9 +17,7 @@ public abstract class LoadableData { this.classificationTypes.add(classificationType); } - public String getClassification() { - return this.classification; - } + public abstract String getClassification() ; public static Set<String> getClassificationTypes() { return classificationTypes; @@ -28,9 +27,7 @@ public abstract class LoadableData { LoadableData.classificationTypes = classificationTypes; } - public void setClassification(String classification) { - this.classification = classification; - } + public abstract void setClassification(String classification); public abstract String[] getAttributesName(); diff --git a/src/main/java/fr/univlille/sae/classification/view/AddDataView.java b/src/main/java/fr/univlille/sae/classification/view/AddDataView.java index 3519b8f09de62b6c2073c9c69f327264d52a9c26..f52b777a7d536b07d41032a0b6412eed913807fa 100644 --- a/src/main/java/fr/univlille/sae/classification/view/AddDataView.java +++ b/src/main/java/fr/univlille/sae/classification/view/AddDataView.java @@ -4,6 +4,7 @@ import fr.univlille.sae.classification.controller.AddDataController; import fr.univlille.sae.classification.controller.AxesSettingsController; import fr.univlille.sae.classification.model.ClassificationModel; import javafx.fxml.FXMLLoader; +import javafx.scene.control.Alert; import javafx.stage.Modality; import javafx.stage.Stage; @@ -41,6 +42,17 @@ public class AddDataView { controller.setMainStageView(mainStageView); + + if(model.getDatas().isEmpty()) { + Alert alert = new Alert(Alert.AlertType.WARNING); + alert.setTitle("Erreur"); + alert.setHeaderText(null); + alert.setContentText("Veuillez d'abord charger les données avant pouvoir ajouter un point"); + alert.showAndWait(); + return; + } + + root.setResizable(false); root.initOwner(owner); root.initModality(Modality.APPLICATION_MODAL); diff --git a/src/main/java/fr/univlille/sae/classification/view/AxesSettingsView.java b/src/main/java/fr/univlille/sae/classification/view/AxesSettingsView.java index d5cc72fb9ca2601314228f8f4a32f204730fd7a1..48ca4ce0f1b8e3369cc350672cb210b2a0bb39e2 100644 --- a/src/main/java/fr/univlille/sae/classification/view/AxesSettingsView.java +++ b/src/main/java/fr/univlille/sae/classification/view/AxesSettingsView.java @@ -5,6 +5,7 @@ import fr.univlille.sae.classification.controller.MainStageController; import fr.univlille.sae.classification.model.ClassificationModel; import fr.univlille.sae.classification.model.LoadableData; import javafx.fxml.FXMLLoader; +import javafx.scene.control.Alert; import javafx.stage.Modality; import javafx.stage.Stage; @@ -43,9 +44,19 @@ public class AxesSettingsView { root.setTitle("Configuration des axes"); AxesSettingsController controller = loader.getController(); + controller.setMainStageView(mainStageView); + + if(model.getDatas().isEmpty()) { + Alert alert = new Alert(Alert.AlertType.WARNING); + alert.setTitle("Erreur"); + alert.setHeaderText(null); + alert.setContentText("Veuillez d'abord charger les données avant de modifier les parametres"); + alert.showAndWait(); + return; + } + LoadableData dataType = model.getDatas().get(0); - controller.setMainStageView(mainStageView); controller.setSelectAbs(dataType.getAttributesName()); controller.setSelectOrd(dataType.getAttributesName()); diff --git a/src/main/java/fr/univlille/sae/classification/view/MainStageView.java b/src/main/java/fr/univlille/sae/classification/view/MainStageView.java index c6ec0e9111813b611e88b298dad7b803cdc66984..9fe2d12ccfa1a9f28748a435b0db46fd9fc83443 100644 --- a/src/main/java/fr/univlille/sae/classification/view/MainStageView.java +++ b/src/main/java/fr/univlille/sae/classification/view/MainStageView.java @@ -13,6 +13,8 @@ import javafx.fxml.FXML; import javafx.fxml.FXMLLoader; import javafx.scene.chart.ScatterChart; import javafx.scene.chart.XYChart; +import javafx.scene.control.ContextMenu; +import javafx.scene.control.MenuItem; import javafx.scene.paint.Color; import javafx.scene.shape.Circle; import javafx.stage.Stage; @@ -20,9 +22,7 @@ import javafx.stage.Stage; import java.io.File; import java.io.IOException; import java.net.URL; -import java.util.ArrayList; -import java.util.List; -import java.util.Random; +import java.util.*; public class MainStageView implements Observer { @@ -32,6 +32,7 @@ public class MainStageView implements Observer { private String actualX; private String actualY; + private Stage root; public MainStageView(ClassificationModel model) { this.model = model; @@ -49,7 +50,7 @@ public class MainStageView implements Observer { System.exit(-1); } loader.setLocation(fxmlFileUrl); - Stage root = loader.load(); + root = loader.load(); root.setResizable(false); root.setTitle("SAE3.3 - Logiciel de classification"); root.show(); @@ -58,36 +59,68 @@ public class MainStageView implements Observer { controller.setMainStageView(this); scatterChart = controller.getScatterChart(); controller.setAxesSelected("Aucun fichier sélectionné"); + } @Override public void update(Observable observable) { if(scatterChart == null) throw new IllegalStateException(); - scatterChart.getData().clear(); if(!(observable instanceof ClassificationModel)) throw new IllegalStateException(); + //on vide le nuage pour s'assurer que celui-ci est bien vide + scatterChart.getData().clear(); + XYChart.Series series1 = new XYChart.Series(); series1.setName("Iris"); + + //Jalon 1: on verifie que le type de donnée est bien IRIS if(model.getType() == DataType.IRIS) { - controller.setAxesSelected(""); + + if(actualX==null && actualY==null){ controller.setAxesSelected("Aucuns axes sélectionnés"); } else{ + controller.setAxesSelected(""); + // On ajoute la serie au nuage scatterChart.getData().add(series1); - for(LoadableData i : model.getDatas()) { + + //On recupere les données du model + List<LoadableData> points = new ArrayList<>(model.getDatas()); + points.addAll(model.getDataToClass()); + // on ajoute chaque point a la serie + for(LoadableData i : points) { + Iris iris = (Iris)i; XYChart.Data<Double, Double> dataPoint = new XYChart.Data<>(iris.getDataType(actualX), iris.getDataType(actualY)); - Circle circle = new Circle(5); - circle.setFill(iris.getColor()); - dataPoint.setNode(circle); + + dataPoint.setNode(getCircle(iris)); + series1.getData().add(dataPoint); + } } } } + + private Circle getCircle(Iris iris) { + Circle circle = new Circle(5); + circle.setFill(iris.getColor()); + circle.setOnMouseClicked(e -> { + ContextMenu contextMenu = new ContextMenu(); + for(String attributes : iris.getAttributesName()) { + contextMenu.getItems().add(new MenuItem(attributes + " : " + iris.getDataType(attributes))); + } + contextMenu.show(root, e.getScreenX(), e.getScreenY()); + }); + + return circle; + } + + + @Override public void update(Observable observable, Object data) { if(scatterChart == null) throw new IllegalStateException(); @@ -102,9 +135,8 @@ public class MainStageView implements Observer { iris.getDataType(actualX), iris.getDataType(actualY) ); - Circle circle = new Circle(5); - circle.setFill(iris.getColor()); - dataPoint.setNode(circle); + + dataPoint.setNode(getCircle(iris)); if (!scatterChart.getData().isEmpty()) { XYChart.Series series = (XYChart.Series) scatterChart.getData().get(0); series.getData().add(dataPoint); @@ -128,7 +160,8 @@ public class MainStageView implements Observer { return actualY; } - public Observable getModel() { - return this.model; + public MainStageController getController() { + return controller; } + }