diff --git a/res/data/error_iris.csv b/res/data/error_iris.csv new file mode 100644 index 0000000000000000000000000000000000000000..350d1471cdab74a6393233a8413ab6bd45cc5cb7 --- /dev/null +++ b/res/data/error_iris.csv @@ -0,0 +1,6 @@ +"sepal.length","sepal.width","petal.length","petal.width","variety" +"abc","xyz","pqr","uvw","Setosa" +"def","lmn","stu","ijk","Setosa" +"ghi","opq","vwx","rst","Setosa" +"jkl","mno","yza","bcd","Setosa" +"qrs","tuv","efg","hij","Setosa" \ No newline at end of file diff --git a/res/stages/main-stage.fxml b/res/stages/main-stage.fxml index 37ee5a84d7934efedc54509dd693ece00867c3b5..c2f1a365d2da7440bf55d75c78c8c07b4d89f91c 100644 --- a/res/stages/main-stage.fxml +++ b/res/stages/main-stage.fxml @@ -1,21 +1,15 @@ <?xml version="1.0" encoding="UTF-8"?> -<?import javafx.geometry.Insets?> -<?import javafx.scene.Scene?> -<?import javafx.scene.chart.NumberAxis?> -<?import javafx.scene.chart.ScatterChart?> -<?import javafx.scene.control.Button?> -<?import javafx.scene.control.Label?> -<?import javafx.scene.control.ListView?> -<?import javafx.scene.image.Image?> -<?import javafx.scene.image.ImageView?> -<?import javafx.scene.layout.AnchorPane?> -<?import javafx.scene.layout.HBox?> -<?import javafx.scene.layout.VBox?> -<?import javafx.scene.text.Font?> -<?import javafx.stage.Stage?> +<?import javafx.geometry.*?> +<?import javafx.scene.*?> +<?import javafx.scene.chart.*?> +<?import javafx.scene.control.*?> +<?import javafx.scene.image.*?> +<?import javafx.scene.layout.*?> +<?import javafx.scene.text.*?> +<?import javafx.stage.*?> -<Stage fx:id="stage" xmlns="http://javafx.com/javafx/21" xmlns:fx="http://javafx.com/fxml/1" fx:controller="fr.univlille.sae.classification.controller.MainStageController"> +<Stage fx:id="stage" xmlns="http://javafx.com/javafx/17.0.2-ea" xmlns:fx="http://javafx.com/fxml/1" fx:controller="fr.univlille.sae.classification.controller.MainStageController"> <scene> <Scene> <AnchorPane prefHeight="535.0" prefWidth="922.0"> @@ -43,7 +37,7 @@ <NumberAxis fx:id="ordAxe" prefHeight="354.0" prefWidth="54.0" side="LEFT" stylesheets="@../css/style.css" /> </yAxis> </ScatterChart> - <Label fx:id="AxesSelected" alignment="CENTER" layoutX="73.0" layoutY="152.0" prefHeight="38.0" prefWidth="600.0"> + <Label fx:id="AxesSelected" alignment="CENTER" layoutX="-2.0" layoutY="3.0" prefHeight="380.0" prefWidth="682.0"> <font> <Font size="21.0" /> </font> 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 21c7e41752c372ff4c8c1e47add3812f136d0e00..9a220bdf4e1c24f8db37dad2a63785c1c25873de 100644 --- a/src/main/java/fr/univlille/sae/classification/controller/AddDataController.java +++ b/src/main/java/fr/univlille/sae/classification/controller/AddDataController.java @@ -90,6 +90,7 @@ public class AddDataController { else if (attrValue instanceof Boolean) { ChoiceBox<String> choiceBox = new ChoiceBox<>(); choiceBox.getItems().addAll("VRAI", "FAUX"); + choiceBox.setValue("VRAI"); hbox.getChildren().add(choiceBox); components.add(choiceBox); } @@ -124,6 +125,7 @@ public class AddDataController { return null; }).toArray(); + System.out.println(Arrays.toString(values)); ClassificationModel.getClassificationModel().ajouterDonnee(values); }catch (IllegalArgumentException e){ Alert alert = new Alert(Alert.AlertType.ERROR); diff --git a/src/main/java/fr/univlille/sae/classification/controller/KNNController.java b/src/main/java/fr/univlille/sae/classification/controller/KNNController.java index def9b3273b96a1a2870403485fa2466c807f98a0..9529531f653a5bad439030706ea8b5f540701ef9 100644 --- a/src/main/java/fr/univlille/sae/classification/controller/KNNController.java +++ b/src/main/java/fr/univlille/sae/classification/controller/KNNController.java @@ -8,9 +8,11 @@ import fr.univlille.sae.classification.model.LoadableData; import javafx.collections.ObservableList; import javafx.concurrent.Task; import javafx.fxml.FXML; +import javafx.geometry.Pos; import javafx.scene.Scene; import javafx.scene.control.*; import javafx.scene.layout.HBox; +import javafx.scene.layout.VBox; import javafx.stage.Stage; import java.util.ArrayList; @@ -59,13 +61,10 @@ public class KNNController { }else { // Calcul du K Optimal: - HBox hBox = new HBox(); - Task<Scene> knnTask = new Task<>() { @Override protected Scene call() throws Exception { - System.out.println("Call call()"); updateProgress(0, 3); updateMessage("Préparation des données "); @@ -104,30 +103,32 @@ public class KNNController { return scene; } }; - + VBox vBox = new VBox(); ProgressBar pBar = new ProgressBar(); pBar.progressProperty().bind(knnTask.progressProperty()); Label statusLabel = new Label(); statusLabel.textProperty().bind(knnTask.messageProperty()); - - hBox.getChildren().addAll(statusLabel, pBar); + vBox.alignmentProperty().setValue(Pos.CENTER); + vBox.getChildren().addAll( pBar, statusLabel); Stage stageLoad = new Stage(); - Scene scene = new Scene(hBox); + Scene scene = new Scene(vBox); + stageLoad.setTitle("Alogirhme K-NN"); + stageLoad.setMinWidth(300); stageLoad.setScene(scene); stageLoad.show(); Stage stageFinished = new Stage(); - + stageFinished.setTitle("Algorithme K-NN - results"); knnTask.setOnSucceeded(e -> { stageLoad.close(); stageFinished.setScene(knnTask.getValue()); stageFinished.show(); }); - knnTask.run(); - //new Thread(knnTask).start(); + + new Thread(knnTask).start(); 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 014af783059a9eb43473293a24c3d30af44c39c2..4baf15fcc240ad98712f30d4d42a49855513be51 100644 --- a/src/main/java/fr/univlille/sae/classification/controller/LoadDataController.java +++ b/src/main/java/fr/univlille/sae/classification/controller/LoadDataController.java @@ -1,5 +1,7 @@ package fr.univlille.sae.classification.controller; +import com.opencsv.exceptions.CsvException; +import com.opencsv.exceptions.CsvRequiredFieldEmptyException; import fr.univlille.sae.classification.model.ClassificationModel; import fr.univlille.sae.classification.model.DataType; import javafx.fxml.FXML; @@ -34,6 +36,7 @@ public class LoadDataController { @FXML public void initialize() { fileType.getItems().addAll(DataType.values()); + fileType.setValue(DataType.values()[0]); } /** @@ -72,7 +75,15 @@ public class LoadDataController { } ClassificationModel.getClassificationModel().setType(typeChoisi); - ClassificationModel.getClassificationModel().loadData(file); + try { + ClassificationModel.getClassificationModel().loadData(file); + }catch (RuntimeException | CsvRequiredFieldEmptyException e) { + Alert alert = new Alert(Alert.AlertType.ERROR); + alert.initOwner(stage); + alert.setHeaderText(e.toString()); + alert.setContentText("Le chargement du fichier à echoué, veuillez reessayer !"); + alert.showAndWait(); + } stage.close(); } } diff --git a/src/main/java/fr/univlille/sae/classification/knn/MethodKNN.java b/src/main/java/fr/univlille/sae/classification/knn/MethodKNN.java index ce462a0b5c12e72f1ac2d9de29bed32aee1006a3..d56d4226ec125293d089f7f2056dc5bc112b0607 100644 --- a/src/main/java/fr/univlille/sae/classification/knn/MethodKNN.java +++ b/src/main/java/fr/univlille/sae/classification/knn/MethodKNN.java @@ -1,5 +1,6 @@ package fr.univlille.sae.classification.knn; +import com.opencsv.exceptions.CsvRequiredFieldEmptyException; import fr.univlille.sae.classification.knn.distance.*; import fr.univlille.sae.classification.model.ClassificationModel; import fr.univlille.sae.classification.model.DataType; @@ -11,6 +12,8 @@ import java.util.*; public class MethodKNN { + // name,attack,base_egg_steps,capture_rate,defense,experience_growth,hp,sp_attack,sp_defense,type1,type2,speed,is_legendary + // Test,45,5800,240.0,50,800000,65,55,65,normal,flying,1.5,False private static final Random random = new Random(); @@ -131,6 +134,7 @@ public class MethodKNN { // On estime la classe chaque donnée de test, et on verifie si l'algo a bon for(LoadableData l : testData) { totalTry++; + System.out.println(l); String baseClass = l.getClassification(); // System.out.println("Base class : " + baseClass); // System.out.println("Base data: " + l); @@ -150,30 +154,28 @@ public class MethodKNN { return taux/(1/testPart); } - public static void main(String[] args) { + public static void main(String[] args) throws CsvRequiredFieldEmptyException { //Test de la robustesse et du meillleur K ClassificationModel model = ClassificationModel.getClassificationModel(); - model.setType(DataType.IRIS); - model.loadData(new File(path+"data/iris.csv")); + model.setType(DataType.POKEMON); + model.loadData(new File(path+"data/pokemon_train.csv")); MethodKNN.updateModel(model.getDatas()); System.out.println(); List<LoadableData> datas = ClassificationModel.getClassificationModel().getDatas(); - // On mélange les données pour tester sur differentes variétes car le fichier de base est trié. - Collections.shuffle(datas); for(int i = 0; i<1; i++) { System.out.println("Search best k"); // On cherche le meilleure K - int bestK = MethodKNN.bestK(datas, new DistanceManhattanNormalisee()); + int bestK = MethodKNN.bestK(datas, new DistanceEuclidienneNormalisee()); System.out.println(bestK); // Puis on clacul la robustesse avec le K trouvé - System.out.println(MethodKNN.robustesse( datas, bestK, new DistanceManhattanNormalisee(), 0.2)); + System.out.println(MethodKNN.robustesse( datas, bestK, new DistanceEuclidienneNormalisee(), 0.2)); } 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 0c5291ca16dadd29e930f2346bec1219feb9c5f5..24b491a1c7d370ef20a53c68031cf1bcbeb851da 100644 --- a/src/main/java/fr/univlille/sae/classification/model/ClassificationModel.java +++ b/src/main/java/fr/univlille/sae/classification/model/ClassificationModel.java @@ -1,6 +1,8 @@ package fr.univlille.sae.classification.model; import com.opencsv.bean.CsvToBeanBuilder; +import com.opencsv.exceptions.CsvBadConverterException; +import com.opencsv.exceptions.CsvRequiredFieldEmptyException; import fr.univlille.sae.classification.knn.MethodKNN; import fr.univlille.sae.classification.knn.distance.Distance; import fr.univlille.sae.classification.knn.distance.DistanceEuclidienne; @@ -79,7 +81,7 @@ public class ClassificationModel extends Observable { * Charge les données à partir d'un fichier CSV. * @param file fichier contenant les données à charger. */ - public void loadData(File file) { + public void loadData(File file) throws CsvRequiredFieldEmptyException, CsvBadConverterException { try { this.datas = new CsvToBeanBuilder<LoadableData>(Files.newBufferedReader(file.toPath())) .withSeparator(',') @@ -137,6 +139,7 @@ public class ClassificationModel extends Observable { public void setDistance(Distance distance) { this.distance = distance; + this.kOptimal = 0; } public Distance getDistance() { 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 e034149b6d6ec8a8ce2f950fcb7aaa44e5bfad36..fbf1734713ae37b123b20e4f9f1f06cbfce9fe32 100644 --- a/src/main/java/fr/univlille/sae/classification/model/Iris.java +++ b/src/main/java/fr/univlille/sae/classification/model/Iris.java @@ -13,13 +13,13 @@ import java.util.Map; */ public class Iris extends LoadableData { - @CsvBindByName(column = "sepal.length") + @CsvBindByName(column = "sepal.length", required = true) private double sepalLength; - @CsvBindByName(column = "sepal.width") + @CsvBindByName(column = "sepal.width", required = true) private double sepalWidth; - @CsvBindByName(column = "petal.length") + @CsvBindByName(column = "petal.length", required = true) private double petalLength; - @CsvBindByName(column = "petal.width") + @CsvBindByName(column = "petal.width", required = true) private double petalWidth; @CsvBindByName(column = "variety") private String variety; diff --git a/src/main/java/fr/univlille/sae/classification/model/PointFactory.java b/src/main/java/fr/univlille/sae/classification/model/PointFactory.java index bddf6995eb5e17c5e48b7de573ec1fa00dbac038..27eba5e9a8c138c2bf0ef639b73bfeada563ed68 100644 --- a/src/main/java/fr/univlille/sae/classification/model/PointFactory.java +++ b/src/main/java/fr/univlille/sae/classification/model/PointFactory.java @@ -32,7 +32,7 @@ public class PointFactory { data = new Pokemon(coords); } else if (coords.length == 11) { - data = new Pokemon((String) coords[0], (Integer) coords[1], (Integer) coords[2], (Double) coords[3], (Integer) coords[4], (Integer) coords[5], (Integer) coords[6], (Integer) coords[7], (Integer) coords[8], "", "", (Double) coords[9], (Boolean) coords[10]); + data = new Pokemon((String) coords[0], (Integer) coords[1], (Integer) coords[2], (Double) coords[3], (Integer) coords[4], (Integer) coords[5], (Integer) coords[6], (Integer) coords[7], (Integer) coords[8], "undefined", "", (Double) coords[9], (Boolean) coords[10]); } break; default: diff --git a/src/main/java/fr/univlille/sae/classification/model/Pokemon.java b/src/main/java/fr/univlille/sae/classification/model/Pokemon.java index 5a251f7d2e1328a5cf0490bf3bd6c708c9503bd7..7ac5fad96ac847d5199b969014b9c3f852fa4e79 100644 --- a/src/main/java/fr/univlille/sae/classification/model/Pokemon.java +++ b/src/main/java/fr/univlille/sae/classification/model/Pokemon.java @@ -49,7 +49,11 @@ public class Pokemon extends LoadableData{ this.hp = hp; this.spAttack = spAttack; this.spDefense = spDefense; - this.type1 = type1; + if(type1 == null || type1.isEmpty()) { + this.type1 = "undefined"; + }else { + this.type1 = type1; + } this.type2 = type2; this.speed = speed; this.isLegendary = isLegendary; @@ -123,7 +127,7 @@ public class Pokemon extends LoadableData{ @Override public String[] getStringAttributes() { - return new String[]{name, type2, String.valueOf(isLegendary)}; + return new String[]{type2, String.valueOf(isLegendary)}; } @Override 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 3c9c13400d3273d647386a4ce8aec774fbaa9c48..39d6cb935722bf87d326a8dd611ede4a49267a0e 100644 --- a/src/main/java/fr/univlille/sae/classification/view/MainStageView.java +++ b/src/main/java/fr/univlille/sae/classification/view/MainStageView.java @@ -8,6 +8,7 @@ import fr.univlille.sae.classification.utils.Observer; import fr.univlille.sae.classification.utils.ViewUtil; import javafx.fxml.FXMLLoader; import javafx.scene.Node; +import javafx.scene.chart.NumberAxis; import javafx.scene.chart.ScatterChart; import javafx.scene.chart.XYChart; import javafx.scene.control.*; @@ -120,6 +121,17 @@ public class MainStageView extends DataVisualizationView implements Observer { Object xValue = data.getAttributesNames().get(actualX); Object yValue = data.getAttributesNames().get(actualY); + + + double x = 0; + if(xValue instanceof Number) { + x = ((Number) xValue).doubleValue(); + } + double y = 0; + if(yValue instanceof Number) { + y = ((Number) yValue).doubleValue(); + } + /** Double x = 0.0; if (xValue instanceof Integer) { x = ((Integer) xValue).doubleValue(); @@ -133,7 +145,7 @@ public class MainStageView extends DataVisualizationView implements Observer { } else if (yValue instanceof Double) { y = (Double) yValue; } - + **/ ScatterChart.Data<Double, Double> dataPoint = new ScatterChart.Data<>(x, y); Node nodePoint = ViewUtil.getForm(data, new Circle(5), controller);